Sync with trunk r58151 to bring the latest changes from Amine and Timo.
[reactos.git] / drivers / storage / ide / uniata / id_ata.cpp
1 /*++
2
3 Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
4
5 Module Name:
6 id_ata.cpp
7
8 Abstract:
9 This is the miniport driver for ATA/ATAPI IDE controllers
10 with Busmaster DMA and Serial ATA support
11
12 Author:
13 Alexander A. Telyatnikov (Alter)
14
15 Environment:
16 kernel mode only
17
18 Notes:
19
20 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 Revision History:
32
33 The skeleton was taken from standard ATAPI.SYS from NT4 DDK by
34 Mike Glass (MGlass)
35 Chuck Park (ChuckP)
36
37 Some parts of code were taken from FreeBSD 4.3-6.1 ATA driver by
38 Søren Schmidt, Copyright (c) 1998-2007
39
40 All parts of code are greatly changed/updated by
41 Alter, Copyright (c) 2002-2007:
42
43 1. Internal command queueing/reordering
44 2. Drive identification
45 3. Support for 2 _independent_ channels in a single PCI device
46 4. Smart host<->drive transfer rate slowdown (for bad cable)
47 5. W2k support (binary compatibility)
48 6. HDD hot swap under NT4
49 7. XP support (binary compatibility)
50 8. Serial ATA (SATA/SATA2/SATA3) support
51 9. NT 3.51 support (binary compatibility)
52
53 etc. (See todo.txt)
54
55
56 --*/
57
58 #include "stdafx.h"
59
60 #ifndef UNIATA_CORE
61
62 static const CHAR ver_string[] = "\n\nATAPI IDE MiniPort Driver (UniATA) v 0." UNIATA_VER_STR "\n";
63
64 static const CHAR uniata_comm_name[] = UNIATA_COMM_PORT_VENDOR_STR " \n";
65
66 UNICODE_STRING SavedRegPath;
67 WCHAR SavedRegPathBuffer[256];
68
69 #endif //UNIATA_CORE
70
71 UCHAR AtaCommands48[256];
72 UCHAR AtaCommandFlags[256];
73
74 ULONG SkipRaids = 1;
75 ULONG ForceSimplex = 0;
76
77 LONGLONG g_Perf = 0;
78 ULONG g_PerfDt = 0;
79
80 #ifdef _DEBUG
81 ULONG g_LogToDisplay = 0;
82 #endif //_DEBUG
83
84 ULONG g_WaitBusyInISR = 1;
85
86 ULONG g_opt_WaitBusyCount = 200; // 20000
87 ULONG g_opt_WaitBusyDelay = 10; // 150
88 ULONG g_opt_WaitDrqDelay = 10; // 100
89 ULONG g_opt_WaitBusyLongCount = 2000; // 2000
90 ULONG g_opt_WaitBusyLongDelay = 250; // 250
91 ULONG g_opt_MaxIsrWait = 40; //
92 BOOLEAN g_opt_AtapiSendDisableIntr = 0; // 0
93 BOOLEAN g_opt_AtapiDmaRawRead = 1; // 0
94 BOOLEAN hasPCI = FALSE;
95
96 ULONG g_opt_VirtualMachine = 0; // Auto
97
98 BOOLEAN InDriverEntry = TRUE;
99
100 BOOLEAN g_opt_Verbose = 0;
101
102 BOOLEAN WinVer_WDM_Model = FALSE;
103
104 //UCHAR EnableDma = FALSE;
105 //UCHAR EnableReorder = FALSE;
106
107 UCHAR g_foo = 0;
108
109 BOOLEAN
110 NTAPI
111 AtapiResetController__(
112 IN PVOID HwDeviceExtension,
113 IN ULONG PathId,
114 IN UCHAR CompleteType
115 );
116
117 VOID
118 NTAPI
119 AtapiHwInitialize__(
120 IN PHW_DEVICE_EXTENSION deviceExtension,
121 IN ULONG lChannel
122 );
123
124 VOID
125 NTAPI
126 UniataUserDeviceReset(
127 PHW_DEVICE_EXTENSION deviceExtension,
128 PHW_LU_EXTENSION LunExt,
129 ULONG lChannel
130 );
131
132 #define RESET_COMPLETE_CURRENT 0x00
133 #define RESET_COMPLETE_ALL 0x01
134 #define RESET_COMPLETE_NONE 0x02
135
136 #ifndef UNIATA_CORE
137
138 VOID
139 NTAPI
140 AtapiCallBack_X(
141 IN PVOID HwDeviceExtension
142 );
143
144 #ifdef UNIATA_USE_XXableInterrupts
145 #define RETTYPE_XXableInterrupts BOOLEAN
146 #define RETVAL_XXableInterrupts TRUE
147 #else
148 #define RETTYPE_XXableInterrupts VOID
149 #define RETVAL_XXableInterrupts
150 #endif
151
152 RETTYPE_XXableInterrupts
153 NTAPI
154 AtapiInterruptDpc(
155 IN PVOID HwDeviceExtension
156 );
157
158 RETTYPE_XXableInterrupts
159 NTAPI
160 AtapiEnableInterrupts__(
161 IN PVOID HwDeviceExtension
162 );
163
164 VOID
165 NTAPI
166 AtapiQueueTimerDpc(
167 IN PVOID HwDeviceExtension,
168 IN ULONG lChannel,
169 IN PHW_TIMER HwScsiTimer,
170 IN ULONG MiniportTimerValue
171 );
172
173 SCSI_ADAPTER_CONTROL_STATUS
174 NTAPI
175 AtapiAdapterControl(
176 IN PVOID HwDeviceExtension,
177 IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
178 IN PVOID Parameters
179 );
180
181 #endif //UNIATA_CORE
182
183 #ifndef UNIATA_CORE
184
185 BOOLEAN
186 NTAPI
187 AtapiRegGetStringParameterValue(
188 IN PWSTR RegistryPath,
189 IN PWSTR Name,
190 IN PWCHAR Str,
191 IN ULONG MaxLen
192 )
193 {
194 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
195 NTSTATUS status;
196 RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
197 UNICODE_STRING ustr;
198
199 ustr.Buffer = Str;
200 ustr.Length =
201 ustr.MaximumLength = (USHORT)MaxLen;
202 RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
203
204 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
205 parameters[0].Name = Name;
206 parameters[0].EntryContext = &ustr;
207 parameters[0].DefaultType = REG_SZ;
208 parameters[0].DefaultData = Str;
209 parameters[0].DefaultLength = MaxLen;
210
211 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
212 RegistryPath, parameters, NULL, NULL);
213
214 if(!NT_SUCCESS(status))
215 return FALSE;
216
217 return TRUE;
218
219 #undef ITEMS_TO_QUERY
220 } // end AtapiRegGetStringParameterValue()
221
222
223 #endif //UNIATA_CORE
224
225 VOID
226 DDKFASTAPI
227 UniataNanoSleep(
228 ULONG nano
229 )
230 {
231 LONGLONG t;
232 LARGE_INTEGER t0;
233
234 #ifdef NAVO_TEST
235 return;
236 #endif //NAVO_TEST
237
238 if(!nano || !g_Perf || !g_PerfDt)
239 return;
240 t = (g_Perf * nano) / g_PerfDt / 1000;
241 if(!t) {
242 t = 1;
243 }
244 do {
245 KeQuerySystemTime(&t0);
246 t--;
247 } while(t);
248 } // end UniataNanoSleep()
249
250 #define AtapiWritePortN_template(_type, _Type, sz) \
251 VOID \
252 DDKFASTAPI \
253 AtapiWritePort##sz( \
254 IN PHW_CHANNEL chan, \
255 IN ULONGIO_PTR _port, \
256 IN _type data \
257 ) \
258 { \
259 PIORES res; \
260 if(_port >= IDX_MAX_REG) { \
261 res = (PIORES)(_port); \
262 } else \
263 if(chan) { \
264 res = &chan->RegTranslation[_port]; \
265 } else { \
266 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
267 return; \
268 } \
269 if(res->Proc) { \
270 } else \
271 if(!res->MemIo) { \
272 ScsiPortWritePort##_Type((_type*)(res->Addr), data); \
273 } else { \
274 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
275 ScsiPortWriteRegister##_Type((_type*)(res->Addr), data); \
276 } \
277 return; \
278 }
279
280 AtapiWritePortN_template(ULONG, Ulong, 4);
281 AtapiWritePortN_template(USHORT, Ushort, 2);
282 AtapiWritePortN_template(UCHAR, Uchar, 1);
283
284 #define AtapiWritePortExN_template(_type, _Type, sz) \
285 VOID \
286 DDKFASTAPI \
287 AtapiWritePortEx##sz( \
288 IN PHW_CHANNEL chan, \
289 IN ULONGIO_PTR _port, \
290 IN ULONG offs, \
291 IN _type data \
292 ) \
293 { \
294 PIORES res; \
295 if(_port >= IDX_MAX_REG) { \
296 res = (PIORES)(_port); \
297 } else \
298 if(chan) { \
299 res = &chan->RegTranslation[_port]; \
300 } else { \
301 KdPrint(("invalid io write request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
302 return; \
303 } \
304 if(res->Proc) { \
305 } else \
306 if(!res->MemIo) { \
307 ScsiPortWritePort##_Type((_type*)(res->Addr+offs), data); \
308 } else { \
309 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
310 ScsiPortWriteRegister##_Type((_type*)(res->Addr+offs), data); \
311 } \
312 return; \
313 }
314
315 AtapiWritePortExN_template(ULONG, Ulong, 4);
316 //AtapiWritePortExN_template(USHORT, Ushort, 2);
317 AtapiWritePortExN_template(UCHAR, Uchar, 1);
318
319 #define AtapiReadPortN_template(_type, _Type, sz) \
320 _type \
321 DDKFASTAPI \
322 AtapiReadPort##sz( \
323 IN PHW_CHANNEL chan, \
324 IN ULONGIO_PTR _port \
325 ) \
326 { \
327 PIORES res; \
328 if(_port >= IDX_MAX_REG) { \
329 res = (PIORES)(_port); \
330 } else \
331 if(chan) { \
332 res = &chan->RegTranslation[_port]; \
333 } else { \
334 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
335 return (_type)(-1); \
336 } \
337 if(res->Proc) { \
338 return 0; \
339 } else \
340 if(!res->MemIo) { \
341 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
342 return ScsiPortReadPort##_Type((_type*)(res->Addr)); \
343 } else { \
344 /*KdPrint(("r_mem @ (%x) %x\n", _port, res->Addr));*/ \
345 return ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
346 } \
347 }
348
349 AtapiReadPortN_template(ULONG, Ulong, 4);
350 AtapiReadPortN_template(USHORT, Ushort, 2);
351 AtapiReadPortN_template(UCHAR, Uchar, 1);
352
353 #define AtapiReadPortExN_template(_type, _Type, sz) \
354 _type \
355 DDKFASTAPI \
356 AtapiReadPortEx##sz( \
357 IN PHW_CHANNEL chan, \
358 IN ULONGIO_PTR _port, \
359 IN ULONG offs \
360 ) \
361 { \
362 PIORES res; \
363 if(_port >= IDX_MAX_REG) { \
364 res = (PIORES)(_port); \
365 } else \
366 if(chan) { \
367 res = &chan->RegTranslation[_port]; \
368 } else { \
369 KdPrint(("invalid io read request @ ch %x, res* %x, offs %x\n", chan, _port, offs)); \
370 return (_type)(-1); \
371 } \
372 if(res->Proc) { \
373 return 0; \
374 } else \
375 if(!res->MemIo) { \
376 return ScsiPortReadPort##_Type((_type*)(res->Addr+offs)); \
377 } else { \
378 /*KdPrint(("r_mem @ (%x) %x\n", _port, port));*/ \
379 return ScsiPortReadRegister##_Type((_type*)(res->Addr+offs)); \
380 } \
381 }
382
383 AtapiReadPortExN_template(ULONG, Ulong, 4);
384 //AtapiReadPortExN_template(USHORT, Ushort, 2);
385 AtapiReadPortExN_template(UCHAR, Uchar, 1);
386
387 #define AtapiReadPortBufferN_template(_type, _Type, sz) \
388 VOID \
389 DDKFASTAPI \
390 AtapiReadBuffer##sz( \
391 IN PHW_CHANNEL chan, \
392 IN ULONGIO_PTR _port, \
393 IN PVOID Buffer, \
394 IN ULONG Count, \
395 IN ULONG Timing \
396 ) \
397 { \
398 PIORES res; \
399 \
400 if(Timing) { \
401 while(Count) { \
402 (*((_type*)Buffer)) = AtapiReadPort##sz(chan, _port); \
403 Count--; \
404 Buffer = ((_type*)Buffer)+1; \
405 UniataNanoSleep(Timing); \
406 } \
407 return; \
408 } \
409 \
410 if(_port >= IDX_MAX_REG) { \
411 res = (PIORES)(_port); \
412 } else \
413 if(chan) { \
414 res = &chan->RegTranslation[_port]; \
415 } else { \
416 KdPrint(("invalid io read request @ ch %x, res* %x\n", chan, _port)); \
417 return; \
418 } \
419 if(!res->MemIo) { \
420 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
421 ScsiPortReadPortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
422 return; \
423 } \
424 while(Count) { \
425 (*((_type*)Buffer)) = ScsiPortReadRegister##_Type((_type*)(res->Addr)); \
426 Count--; \
427 Buffer = ((_type*)Buffer)+1; \
428 } \
429 return; \
430 }
431
432 #define AtapiWritePortBufferN_template(_type, _Type, sz) \
433 VOID \
434 DDKFASTAPI \
435 AtapiWriteBuffer##sz( \
436 IN PHW_CHANNEL chan, \
437 IN ULONGIO_PTR _port, \
438 IN PVOID Buffer, \
439 IN ULONG Count, \
440 IN ULONG Timing \
441 ) \
442 { \
443 PIORES res; \
444 \
445 if(Timing) { \
446 while(Count) { \
447 AtapiWritePort##sz(chan, _port, *((_type*)Buffer)); \
448 Buffer = ((_type*)Buffer)+1; \
449 Count--; \
450 UniataNanoSleep(Timing); \
451 } \
452 return; \
453 } \
454 \
455 if(_port >= IDX_MAX_REG) { \
456 res = (PIORES)(_port); \
457 } else \
458 if(chan) { \
459 res = &chan->RegTranslation[_port]; \
460 } else { \
461 KdPrint(("invalid io write request @ ch %x, res* %x\n", chan, _port)); \
462 return; \
463 } \
464 if(!res->MemIo) { \
465 /*KdPrint(("r_io @ (%x) %x\n", _port, res->Addr));*/ \
466 ScsiPortWritePortBuffer##_Type((_type*)(res->Addr), (_type*)Buffer, Count); \
467 return; \
468 } \
469 while(Count) { \
470 ScsiPortWriteRegister##_Type((_type*)(res->Addr), *((_type*)Buffer)); \
471 Count--; \
472 Buffer = ((_type*)Buffer)+1; \
473 } \
474 return; \
475 }
476
477 AtapiWritePortBufferN_template(ULONG, Ulong, 4);
478 AtapiWritePortBufferN_template(USHORT, Ushort, 2);
479
480 AtapiReadPortBufferN_template(ULONG, Ulong, 4);
481 AtapiReadPortBufferN_template(USHORT, Ushort, 2);
482
483
484 UCHAR
485 DDKFASTAPI
486 AtapiSuckPort2(
487 IN PHW_CHANNEL chan
488 )
489 {
490 UCHAR statusByte;
491 ULONG i;
492
493 // Assume, proper drive is already seleted
494 WaitOnBusyLong(chan);
495 for (i = 0; i < 0x10000; i++) {
496
497 GetStatus(chan, statusByte);
498 if (statusByte & IDE_STATUS_DRQ) {
499 // Suck out any remaining bytes and throw away.
500 AtapiReadPort2(chan, IDX_IO1_i_Data);
501 } else {
502 break;
503 }
504 }
505 if(i) {
506 KdPrint2((PRINT_PREFIX "AtapiSuckPort2: overrun detected (%#x words)\n", i ));
507 }
508 return statusByte;
509 } // AtapiSuckPort2()
510
511 UCHAR
512 DDKFASTAPI
513 WaitOnBusy(
514 IN PHW_CHANNEL chan
515 )
516 {
517 ULONG i;
518 UCHAR Status;
519
520 GetStatus(chan, Status);
521 for (i=0; i<g_opt_WaitBusyCount; i++) {
522 if (Status & IDE_STATUS_BUSY) {
523 AtapiStallExecution(g_opt_WaitBusyDelay);
524 GetStatus(chan, Status);
525 continue;
526 } else {
527 break;
528 }
529 }
530 return Status;
531 } // end WaitOnBusy()
532
533 UCHAR
534 DDKFASTAPI
535 WaitOnBusyLong(
536 IN PHW_CHANNEL chan
537 )
538 {
539 ULONG i;
540 UCHAR Status;
541
542 Status = WaitOnBusy(chan);
543 if(!(Status & IDE_STATUS_BUSY))
544 return Status;
545 for (i=0; i<g_opt_WaitBusyLongCount; i++) {
546 GetStatus(chan, Status);
547 if (Status & IDE_STATUS_BUSY) {
548 AtapiStallExecution(g_opt_WaitBusyLongDelay);
549 continue;
550 } else {
551 break;
552 }
553 }
554 return Status;
555 } // end WaitOnBusyLong()
556
557 UCHAR
558 DDKFASTAPI
559 WaitOnBaseBusy(
560 IN PHW_CHANNEL chan
561 )
562 {
563 ULONG i;
564 UCHAR Status = IDE_STATUS_WRONG;
565 for (i=0; i<g_opt_WaitBusyCount; i++) {
566 GetBaseStatus(chan, Status);
567 if (Status & IDE_STATUS_BUSY) {
568 AtapiStallExecution(g_opt_WaitBusyDelay);
569 continue;
570 } else {
571 break;
572 }
573 }
574 return Status;
575 } // end WaitOnBaseBusy()
576
577 UCHAR
578 DDKFASTAPI
579 WaitOnBaseBusyLong(
580 IN PHW_CHANNEL chan
581 )
582 {
583 ULONG i;
584 UCHAR Status;
585
586 Status = WaitOnBaseBusy(chan);
587 if(!(Status & IDE_STATUS_BUSY))
588 return Status;
589 for (i=0; i<2000; i++) {
590 GetBaseStatus(chan, Status);
591 if (Status & IDE_STATUS_BUSY) {
592 AtapiStallExecution(250);
593 continue;
594 } else {
595 break;
596 }
597 }
598 return Status;
599 } // end WaitOnBaseBusyLong()
600
601 UCHAR
602 DDKFASTAPI
603 UniataIsIdle(
604 IN struct _HW_DEVICE_EXTENSION* deviceExtension,
605 IN UCHAR Status
606 )
607 {
608 UCHAR Status2;
609
610 if(Status == IDE_STATUS_WRONG) {
611 return IDE_STATUS_WRONG;
612 }
613 if(Status & IDE_STATUS_BUSY) {
614 return Status;
615 }
616 // if(deviceExtension->HwFlags & UNIATA_SATA) {
617 if(UniataIsSATARangeAvailable(deviceExtension, 0)) {
618 if(Status & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
619 return Status;
620 }
621 } else {
622 Status2 = Status & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX);
623 if ((Status & IDE_STATUS_BUSY) ||
624 (Status2 != IDE_STATUS_IDLE && Status2 != IDE_STATUS_DRDY)) {
625 return Status;
626 }
627 }
628 return IDE_STATUS_IDLE;
629 } // end UniataIsIdle()
630
631 UCHAR
632 DDKFASTAPI
633 WaitForIdleLong(
634 IN PHW_CHANNEL chan
635 )
636 {
637 ULONG i;
638 UCHAR Status;
639 UCHAR Status2;
640 for (i=0; i<20000; i++) {
641 GetStatus(chan, Status);
642 Status2 = UniataIsIdle(chan->DeviceExtension, Status);
643 if(Status2 == IDE_STATUS_WRONG) {
644 // no drive ?
645 break;
646 } else
647 if(Status2 & IDE_STATUS_BUSY) {
648 AtapiStallExecution(10);
649 continue;
650 } else {
651 break;
652 }
653 }
654 return Status;
655 } // end WaitForIdleLong()
656
657 UCHAR
658 DDKFASTAPI
659 WaitForDrq(
660 IN PHW_CHANNEL chan
661 )
662 {
663 ULONG i;
664 UCHAR Status;
665 for (i=0; i<1000; i++) {
666 GetStatus(chan, Status);
667 if (Status & IDE_STATUS_BUSY) {
668 AtapiStallExecution(g_opt_WaitDrqDelay);
669 } else if (Status & IDE_STATUS_DRQ) {
670 break;
671 } else {
672 AtapiStallExecution(g_opt_WaitDrqDelay*2);
673 }
674 }
675 return Status;
676 } // end WaitForDrq()
677
678 UCHAR
679 DDKFASTAPI
680 WaitShortForDrq(
681 IN PHW_CHANNEL chan
682 )
683 {
684 ULONG i;
685 UCHAR Status;
686 for (i=0; i<2; i++) {
687 GetStatus(chan, Status);
688 if (Status & IDE_STATUS_BUSY) {
689 AtapiStallExecution(g_opt_WaitDrqDelay);
690 } else if (Status & IDE_STATUS_DRQ) {
691 break;
692 } else {
693 AtapiStallExecution(g_opt_WaitDrqDelay);
694 }
695 }
696 return Status;
697 } // end WaitShortForDrq()
698
699 VOID
700 DDKFASTAPI
701 AtapiSoftReset(
702 IN PHW_CHANNEL chan,
703 ULONG DeviceNumber
704 )
705 {
706 //ULONG c = chan->lChannel;
707 ULONG i = 30 * 1000;
708 UCHAR dma_status = 0;
709 KdPrint2((PRINT_PREFIX "AtapiSoftReset:\n"));
710 UCHAR statusByte2;
711
712 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
713 UniataAhciSoftReset(chan->DeviceExtension, chan->lChannel, DeviceNumber);
714 return;
715 }
716
717 GetBaseStatus(chan, statusByte2);
718 KdPrint2((PRINT_PREFIX " statusByte2 %x:\n", statusByte2));
719 SelectDrive(chan, DeviceNumber);
720 if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MANUAL_CHS) {
721 // For ESDI/MFM
722 AtapiStallExecution(10000);
723 for (i = 0; i < 1000; i++) {
724 AtapiStallExecution(999);
725 }
726 } else {
727 AtapiStallExecution(500);
728 GetBaseStatus(chan, statusByte2);
729 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_RESET);
730
731 // Do not wait for BUSY assertion if it was initially set, jump to
732 // BUSY release wait loop
733 if(!(statusByte2 & IDE_STATUS_BUSY)) {
734 // Wait for BUSY assertion, in some cases delay may occure
735 // 100ms should be enough
736 i = 10*1000;
737 while (!(AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
738 i--)
739 {
740 AtapiStallExecution(10);
741 }
742 }
743
744 i = 30 * 1000;
745 // ReactOS modification: Already stop looping when we know that the drive has finished resetting.
746 // Not all controllers clear the IDE_STATUS_BUSY flag (e.g. not the VMware one), so ensure that
747 // the maximum waiting time (30 * i = 0.9 seconds) does not exceed the one of the original
748 // implementation. (which is around 1 second)
749 while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) &&
750 i--)
751 {
752 AtapiStallExecution(30);
753 }
754 }
755
756 SelectDrive(chan, DeviceNumber);
757 WaitOnBusy(chan);
758 GetBaseStatus(chan, statusByte2);
759 AtapiStallExecution(500);
760
761 GetBaseStatus(chan, statusByte2);
762 if(chan && chan->DeviceExtension) {
763 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
764 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
765 } else {
766 KdPrint2((PRINT_PREFIX " can't get DMA status\n"));
767 }
768 if(dma_status & BM_STATUS_INTR) {
769 // bullshit, we have DMA interrupt, but had never initiate DMA operation
770 KdPrint2((PRINT_PREFIX " clear unexpected DMA intr on ATAPI reset\n"));
771 AtapiDmaDone(chan->DeviceExtension, DeviceNumber, chan->lChannel, NULL);
772 GetBaseStatus(chan, statusByte2);
773 }
774 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
775 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, DeviceNumber);
776 /* if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
777 UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1);
778 }*/
779 }
780 return;
781
782 } // end AtapiSoftReset()
783
784 /*
785 Send command to device.
786 Translate to 48-Lba form if required
787 */
788 UCHAR
789 NTAPI
790 AtaCommand48(
791 IN PHW_DEVICE_EXTENSION deviceExtension,
792 IN ULONG DeviceNumber,
793 IN ULONG lChannel,
794 IN UCHAR command,
795 IN ULONGLONG lba,
796 IN USHORT count,
797 IN USHORT feature,
798 IN ULONG wait_flags
799 )
800 {
801 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
802 UCHAR statusByte;
803 ULONG i;
804 PUCHAR plba;
805
806 KdPrint2((PRINT_PREFIX "AtaCommand48: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x count %#x feature %#x\n",
807 deviceExtension->DevIndex, deviceExtension->Channel, DeviceNumber, command, lba, count, feature ));
808
809 if(deviceExtension->HwFlags & UNIATA_AHCI) {
810 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd);
811
812 KdPrint3((" (ahci)\n"));
813
814 statusByte = UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
815 (PSCSI_REQUEST_BLOCK)NULL,
816 NULL,
817 0,
818 command,
819 lba, count,
820 feature,
821 0 /* ahci flags */ ,
822 wait_flags,
823 1000 /* timeout 1 sec */
824 );
825
826 return statusByte;
827 }
828
829 SelectDrive(chan, DeviceNumber);
830
831 statusByte = WaitOnBusy(chan);
832
833 /* ready to issue command ? */
834 if (statusByte & IDE_STATUS_BUSY) {
835 KdPrint2((PRINT_PREFIX " Returning BUSY status\n"));
836 return statusByte;
837 }
838 // !!! We should not check ERROR condition here
839 // ERROR bit may be asserted durring previous operation
840 // and not cleared after SELECT
841
842 //>>>>>> NV: 2006/08/03
843 if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) &&
844 CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) {
845 KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count));
846 return IDE_STATUS_ERROR;
847 //return SRB_STATUS_ERROR;
848 }
849 //<<<<<< NV: 2006/08/03
850
851 /* only use 48bit addressing if needed because of the overhead */
852 if (UniAta_need_lba48(command, lba, count,
853 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48)) {
854
855 KdPrint2((PRINT_PREFIX " dev %#x USE_LBA_48\n", DeviceNumber ));
856 /* translate command into 48bit version */
857 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) {
858 command = AtaCommands48[command];
859 } else {
860 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n"));
861 return (UCHAR)-1;
862 }
863
864 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48;
865 plba = (PUCHAR)&lba;
866
867 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)(feature>>8));
868 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature);
869 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)(count>>8));
870 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count);
871 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[3]));
872 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)(plba[0]));
873 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[4]));
874 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)(plba[1]));
875 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[5]));
876 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)(plba[2]));
877
878 //KdPrint2((PRINT_PREFIX "AtaCommand48: dev %#x USE_LBA48 (2)\n", DeviceNumber ));
879 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1) );
880 } else {
881
882 plba = (PUCHAR)&lba; //ktp
883 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48;
884
885 //if(feature ||
886 // (chan->lun[DeviceNumber]->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))) {
887 AtapiWritePort1(chan, IDX_IO1_o_Feature, (UCHAR)feature);
888 //}
889 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, (UCHAR)count);
890 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, (UCHAR)plba[0]);
891 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, (UCHAR)plba[1]);
892 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, (UCHAR)plba[2]);
893 if(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_LBA_ENABLED) {
894 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_LBA\n", DeviceNumber ));
895 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
896 } else {
897 //KdPrint2((PRINT_PREFIX "AtaCommand28: dev %#x USE_CHS\n", DeviceNumber ));
898 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, (UCHAR)(plba[3] & 0xf) | (DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1) );
899 }
900 }
901
902 // write command code to device
903 AtapiWritePort1(chan, IDX_IO1_o_Command, command);
904
905 switch (wait_flags) {
906 case ATA_WAIT_INTR:
907
908 // caller requested wait for interrupt
909 for(i=0;i<4;i++) {
910 WaitOnBusy(chan);
911 statusByte = WaitForDrq(chan);
912 if (statusByte & IDE_STATUS_DRQ)
913 break;
914 AtapiStallExecution(500);
915 KdPrint2((PRINT_PREFIX " retry waiting DRQ, status %#x\n", statusByte));
916 }
917
918 return statusByte;
919
920 case ATA_WAIT_IDLE:
921
922 // caller requested wait for entering Wait state
923 for (i=0; i<30 * 1000; i++) {
924
925 GetStatus(chan, statusByte);
926 statusByte = UniataIsIdle(deviceExtension, statusByte);
927 if(statusByte == IDE_STATUS_WRONG) {
928 // no drive ?
929 break;
930 } else
931 if(statusByte & IDE_STATUS_ERROR) {
932 break;
933 } else
934 if(statusByte & IDE_STATUS_BUSY) {
935 AtapiStallExecution(100);
936 continue;
937 } else
938 if(statusByte == IDE_STATUS_IDLE) {
939 break;
940 } else {
941 //if(deviceExtension->HwFlags & UNIATA_SATA) {
942 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
943 break;
944 }
945 AtapiStallExecution(100);
946 }
947 }
948 //statusByte |= IDE_STATUS_BUSY;
949 break;
950
951 case ATA_WAIT_READY:
952 statusByte = WaitOnBusyLong(chan);
953 break;
954 case ATA_WAIT_BASE_READY:
955 statusByte = WaitOnBaseBusyLong(chan);
956 break;
957 case ATA_IMMEDIATE:
958 GetStatus(chan, statusByte);
959 if (statusByte & IDE_STATUS_ERROR) {
960 KdPrint2((PRINT_PREFIX " Warning: Immed Status %#x :(\n", statusByte));
961 if(statusByte == (IDE_STATUS_IDLE | IDE_STATUS_ERROR)) {
962 break;
963 }
964 KdPrint2((PRINT_PREFIX " try to continue\n"));
965 statusByte &= ~IDE_STATUS_ERROR;
966 }
967 UniataExpectChannelInterrupt(chan, TRUE);
968 // !!!!!
969 InterlockedExchange(&(chan->CheckIntr),
970 CHECK_INTR_IDLE);
971 statusByte = 0;
972 break;
973 }
974
975 KdPrint2((PRINT_PREFIX " Status %#x\n", statusByte));
976
977 return statusByte;
978 } // end AtaCommand48()
979
980 /*
981 Send command to device.
982 This is simply wrapper for AtaCommand48()
983 */
984 UCHAR
985 NTAPI
986 AtaCommand(
987 IN PHW_DEVICE_EXTENSION deviceExtension,
988 IN ULONG DeviceNumber,
989 IN ULONG lChannel,
990 IN UCHAR command,
991 IN USHORT cylinder,
992 IN UCHAR head,
993 IN UCHAR sector,
994 IN UCHAR count,
995 IN UCHAR feature,
996 IN ULONG wait_flags
997 )
998 {
999 if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
1000 return AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1001 command,
1002 (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
1003 count, feature, wait_flags);
1004 } else {
1005 return UniataAhciSendPIOCommand(deviceExtension, lChannel, DeviceNumber,
1006 (PSCSI_REQUEST_BLOCK)NULL,
1007 NULL,
1008 0,
1009 command,
1010 (ULONG)sector | ((ULONG)cylinder << 8) | ((ULONG)(head & 0x0f) << 24),
1011 count,
1012 feature,
1013 0 /* ahci flags */ ,
1014 wait_flags,
1015 1000 /* timeout 1 sec */
1016 );
1017
1018 }
1019 } // end AtaCommand()
1020
1021 LONG
1022 NTAPI
1023 AtaPio2Mode(LONG pio)
1024 {
1025 switch (pio) {
1026 default: return ATA_PIO;
1027 case 0: return ATA_PIO0;
1028 case 1: return ATA_PIO1;
1029 case 2: return ATA_PIO2;
1030 case 3: return ATA_PIO3;
1031 case 4: return ATA_PIO4;
1032 case 5: return ATA_PIO5;
1033 }
1034 } // end AtaPio2Mode()
1035
1036 LONG
1037 NTAPI
1038 AtaPioMode(PIDENTIFY_DATA2 ident)
1039 {
1040 if (ident->PioTimingsValid) {
1041 if (ident->AdvancedPIOModes & AdvancedPIOModes_5)
1042 return 5;
1043 if (ident->AdvancedPIOModes & AdvancedPIOModes_4)
1044 return 4;
1045 if (ident->AdvancedPIOModes & AdvancedPIOModes_3)
1046 return 3;
1047 }
1048 if (ident->PioCycleTimingMode == 2)
1049 return 2;
1050 if (ident->PioCycleTimingMode == 1)
1051 return 1;
1052 if (ident->PioCycleTimingMode == 0)
1053 return 0;
1054 return IOMODE_NOT_SPECIFIED;
1055 } // end AtaPioMode()
1056
1057 LONG
1058 NTAPI
1059 AtaWmode(PIDENTIFY_DATA2 ident)
1060 {
1061 if (ident->MultiWordDMASupport & 0x04)
1062 return 2;
1063 if (ident->MultiWordDMASupport & 0x02)
1064 return 1;
1065 if (ident->MultiWordDMASupport & 0x01)
1066 return 0;
1067 return IOMODE_NOT_SPECIFIED;
1068 } // end AtaWmode()
1069
1070 LONG
1071 NTAPI
1072 AtaUmode(PIDENTIFY_DATA2 ident)
1073 {
1074 if (!ident->UdmaModesValid)
1075 return IOMODE_NOT_SPECIFIED;
1076 if (ident->UltraDMASupport & 0x40)
1077 return 6;
1078 if (ident->UltraDMASupport & 0x20)
1079 return 5;
1080 if (ident->UltraDMASupport & 0x10)
1081 return 4;
1082 if (ident->UltraDMASupport & 0x08)
1083 return 3;
1084 if (ident->UltraDMASupport & 0x04)
1085 return 2;
1086 if (ident->UltraDMASupport & 0x02)
1087 return 1;
1088 if (ident->UltraDMASupport & 0x01)
1089 return 0;
1090 return IOMODE_NOT_SPECIFIED;
1091 } // end AtaUmode()
1092
1093 LONG
1094 NTAPI
1095 AtaSAmode(PIDENTIFY_DATA2 ident) {
1096 if(!ident->SataCapabilities ||
1097 ident->SataCapabilities == 0xffff) {
1098 return IOMODE_NOT_SPECIFIED;
1099 }
1100 if(ident->SataCapabilities & ATA_SATA_GEN3) {
1101 return ATA_SA600;
1102 } else
1103 if(ident->SataCapabilities & ATA_SATA_GEN2) {
1104 return ATA_SA300;
1105 } else
1106 if(ident->SataCapabilities & ATA_SATA_GEN1) {
1107 return ATA_SA150;
1108 }
1109 return IOMODE_NOT_SPECIFIED;
1110 } // end AtaSAmode()
1111
1112 #ifndef UNIATA_CORE
1113
1114 VOID
1115 NTAPI
1116 AtapiTimerDpc(
1117 IN PVOID HwDeviceExtension
1118 )
1119 {
1120 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1121 PHW_TIMER HwScsiTimer;
1122 LARGE_INTEGER time;
1123 ULONG MiniportTimerValue;
1124 BOOLEAN recall = FALSE;
1125 ULONG lChannel;
1126 PHW_CHANNEL chan;
1127
1128 KdPrint2((PRINT_PREFIX "AtapiTimerDpc:\n"));
1129
1130 lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1131 if(lChannel == CHAN_NOT_SPECIFIED) {
1132 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no items\n"));
1133 return;
1134 }
1135 chan = &(deviceExtension->chan[lChannel]);
1136
1137 while(TRUE) {
1138
1139 HwScsiTimer = chan->HwScsiTimer;
1140 chan->HwScsiTimer = NULL;
1141
1142 deviceExtension->FirstDpcChan = chan->NextDpcChan;
1143 if(deviceExtension->FirstDpcChan != CHAN_NOT_SPECIFIED) {
1144 recall = TRUE;
1145 }
1146
1147 HwScsiTimer(HwDeviceExtension);
1148
1149 chan->NextDpcChan = CHAN_NOT_SPECIFIED;
1150
1151 lChannel = deviceExtension->ActiveDpcChan = deviceExtension->FirstDpcChan;
1152 if(lChannel == CHAN_NOT_SPECIFIED) {
1153 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: no more items\n"));
1154 deviceExtension->FirstDpcChan =
1155 deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1156 return;
1157 }
1158
1159 KeQuerySystemTime(&time);
1160 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1161
1162 chan = &deviceExtension->chan[lChannel];
1163 if(time.QuadPart >= chan->DpcTime - 10) {
1164 // call now
1165 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: get next DPC, DpcTime1=%#x%#x\n",
1166 (ULONG)(chan->DpcTime >> 32), (ULONG)(chan->DpcTime)));
1167 continue;
1168 }
1169 break;
1170 }
1171
1172 if(recall) {
1173 deviceExtension->ActiveDpcChan = CHAN_NOT_SPECIFIED;
1174 MiniportTimerValue = (ULONG)(time.QuadPart - chan->DpcTime)/10;
1175 if(!MiniportTimerValue)
1176 MiniportTimerValue = 1;
1177
1178 KdPrint2((PRINT_PREFIX "AtapiTimerDpc: recall AtapiTimerDpc\n"));
1179 ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1180 AtapiTimerDpc,
1181 MiniportTimerValue
1182 );
1183 }
1184 return;
1185
1186 } // end AtapiTimerDpc()
1187
1188 /*
1189 Wrapper for ScsiPort, that implements smart Dpc
1190 queueing. We need it to allow parallel functioning
1191 of IDE channles with shared interrupt. Standard Dpc mechanism
1192 cancels previous Dpc request (if any), but we need Dpc queue.
1193 */
1194 VOID
1195 NTAPI
1196 AtapiQueueTimerDpc(
1197 IN PVOID HwDeviceExtension,
1198 IN ULONG lChannel,
1199 IN PHW_TIMER HwScsiTimer,
1200 IN ULONG MiniportTimerValue
1201 )
1202 {
1203 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1204 LARGE_INTEGER time;
1205 LARGE_INTEGER time2;
1206 ULONG i;
1207 PHW_CHANNEL prev_chan;
1208 PHW_CHANNEL chan;
1209 // BOOLEAN UseRequestTimerCall = TRUE;
1210
1211 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1212 KeQuerySystemTime(&time);
1213 time2 = time;
1214 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime=%#x%#x\n", time.HighPart, time.LowPart));
1215 time.QuadPart += MiniportTimerValue*10;
1216 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime2=%#x%#x\n", time.HighPart, time.LowPart));
1217
1218 KdPrint2((PRINT_PREFIX " ActiveDpcChan=%d, FirstDpcChan=%d\n", deviceExtension->ActiveDpcChan, deviceExtension->FirstDpcChan));
1219
1220 i = deviceExtension->FirstDpcChan;
1221 chan = prev_chan = NULL;
1222 while(i != CHAN_NOT_SPECIFIED) {
1223 prev_chan = chan;
1224 chan = &(deviceExtension->chan[i]);
1225 if(chan->DpcTime > time.QuadPart) {
1226 break;
1227 }
1228 i = chan->NextDpcChan;
1229 }
1230 chan = &(deviceExtension->chan[lChannel]);
1231 if(!prev_chan) {
1232 deviceExtension->FirstDpcChan = lChannel;
1233 } else {
1234 prev_chan->NextDpcChan = lChannel;
1235 }
1236 chan->NextDpcChan = i;
1237 chan->HwScsiTimer = HwScsiTimer;
1238 chan->DpcTime = time.QuadPart;
1239
1240 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: KeQuerySystemTime3=%#x%#x\n", time2.HighPart, time2.LowPart));
1241 if(time.QuadPart <= time2.QuadPart) {
1242 MiniportTimerValue = 1;
1243 } else {
1244 MiniportTimerValue = (ULONG)((time.QuadPart - time2.QuadPart) / 10);
1245 }
1246
1247 KdPrint2((PRINT_PREFIX "AtapiQueueTimerDpc: dt=%d for lChn %#x\n", MiniportTimerValue, lChannel));
1248 ScsiPortNotification(RequestTimerCall, HwDeviceExtension,
1249 AtapiTimerDpc,
1250 MiniportTimerValue);
1251
1252 } // end AtapiQueueTimerDpc()
1253
1254 #endif //UNIATA_CORE
1255
1256 #if DBG
1257 VOID
1258 NTAPI
1259 UniataDumpATARegs(
1260 IN PHW_CHANNEL chan
1261 )
1262 {
1263 ULONG j;
1264 UCHAR statusByteAlt;
1265
1266 GetStatus(chan, statusByteAlt);
1267 KdPrint2((PRINT_PREFIX " AltStatus (%#x)\n", statusByteAlt));
1268
1269 for(j=1; j<IDX_IO1_SZ; j++) {
1270 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1271 KdPrint2((PRINT_PREFIX
1272 " Reg_%#x (%#x) = %#x\n",
1273 j,
1274 chan->RegTranslation[IDX_IO1+j].Addr,
1275 statusByteAlt));
1276 }
1277 for(j=0; j<IDX_BM_IO_SZ-1; j++) {
1278 statusByteAlt = AtapiReadPort1(chan, IDX_BM_IO+j);
1279 KdPrint2((PRINT_PREFIX
1280 " BM_%#x (%#x) = %#x\n",
1281 j,
1282 chan->RegTranslation[IDX_BM_IO+j].Addr,
1283 statusByteAlt));
1284 }
1285 return;
1286 } // end UniataDumpATARegs()
1287 #endif
1288
1289 VOID
1290 NTAPI
1291 UniataSnapAtaRegs(
1292 IN PHW_CHANNEL chan,
1293 IN ULONG DeviceNumber,
1294 IN OUT PIDEREGS_EX regs
1295 )
1296 {
1297 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
1298 // AHCI
1299 UniataAhciSnapAtaRegs(chan, DeviceNumber, regs);
1300 } else {
1301 // SATA/PATA, assume drive is selected
1302 ULONG j;
1303 UCHAR statusByteAlt;
1304
1305 if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) {
1306 for(j=IDX_IO1_i_Error; j<=IDX_IO1_i_Status; j++) {
1307 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1308 ((PUCHAR)regs)[j-1] = statusByteAlt;
1309 }
1310 regs->bOpFlags = 0;
1311 } else {
1312 regs->bDriveHeadReg = AtapiReadPort1(chan, IDX_IO1_i_DriveSelect);
1313 for(j=IDX_IO1_i_Error; j<IDX_IO1_i_DriveSelect; j++) {
1314 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1315 ((PUCHAR)regs)[j-1] = statusByteAlt;
1316 statusByteAlt = AtapiReadPort1(chan, IDX_IO1+j);
1317 ((PUCHAR)regs)[j+8-1] = statusByteAlt;
1318 }
1319 regs->bCommandReg = AtapiReadPort1(chan, IDX_IO1_i_Status);
1320 }
1321 }
1322 return;
1323 } // end UniataSnapAtaRegs()
1324
1325 /*++
1326
1327 Routine Description:
1328
1329 Issue IDENTIFY command to a device.
1330
1331 Arguments:
1332
1333 HwDeviceExtension - HBA miniport driver's adapter data storage
1334 DeviceNumber - Indicates which device.
1335 Command - Either the standard (EC) or the ATAPI packet (A1) IDENTIFY.
1336
1337 Return Value:
1338
1339 TRUE if all goes well.
1340
1341 --*/
1342 BOOLEAN
1343 NTAPI
1344 IssueIdentify(
1345 IN PVOID HwDeviceExtension,
1346 IN ULONG DeviceNumber,
1347 IN ULONG lChannel,
1348 IN UCHAR Command,
1349 IN BOOLEAN NoSetup
1350 )
1351 {
1352 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
1353 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
1354 ULONG waitCount = 50000;
1355 ULONG j;
1356 UCHAR statusByte;
1357 UCHAR statusByte2;
1358 UCHAR signatureLow,
1359 signatureHigh;
1360 BOOLEAN atapiDev = FALSE;
1361 BOOLEAN use_ahci = FALSE;
1362 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
1363
1364 use_ahci = UniataIsSATARangeAvailable(deviceExtension, lChannel) &&
1365 (deviceExtension->HwFlags & UNIATA_AHCI);
1366
1367 if(chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) {
1368 if(chan->PmLunMap & (1 << DeviceNumber)) {
1369 // OK
1370 } else {
1371 KdPrint2((PRINT_PREFIX "IssueIdentify: PM empty port\n"));
1372 return FALSE;
1373 }
1374 } else
1375 if(DeviceNumber && (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
1376 KdPrint2((PRINT_PREFIX "IssueIdentify: NO SLAVE\n"));
1377 return FALSE;
1378 }
1379 if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
1380 KdPrint2((PRINT_PREFIX "IssueIdentify: HIDDEN\n"));
1381 return FALSE;
1382 }
1383
1384 if(use_ahci) {
1385 statusByte = WaitOnBusyLong(chan);
1386 #if DBG
1387 if(!chan->AhciInternalAtaReq) {
1388 KdPrint2((PRINT_PREFIX "!AhciInternalAtaReq\n"));
1389 }
1390 #endif
1391 } else {
1392 SelectDrive(chan, DeviceNumber);
1393 AtapiStallExecution(10);
1394 statusByte = WaitOnBusyLong(chan);
1395 // Check that the status register makes sense.
1396 GetBaseStatus(chan, statusByte2);
1397 }
1398
1399 if (Command == IDE_COMMAND_IDENTIFY) {
1400 // Mask status byte ERROR bits.
1401 statusByte = UniataIsIdle(deviceExtension, statusByte & ~(IDE_STATUS_ERROR | IDE_STATUS_INDEX));
1402 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for IDE. Status (%#x)\n", statusByte));
1403 // Check if register value is reasonable.
1404
1405 if(statusByte != IDE_STATUS_IDLE) {
1406
1407 // No reset here !!!
1408 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte != IDE_STATUS_IDLE\n"));
1409
1410 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1411 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1412 SelectDrive(chan, DeviceNumber);
1413 WaitOnBusyLong(chan);
1414
1415 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1416 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1417
1418 if (signatureLow == ATAPI_MAGIC_LSB &&
1419 signatureHigh == ATAPI_MAGIC_MSB) {
1420 // Device is Atapi.
1421 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (dev %d)\n", DeviceNumber));
1422 return FALSE;
1423 }
1424
1425 // We really should wait up to 31 seconds
1426 // The ATA spec. allows device 0 to come back from BUSY in 31 seconds!
1427 // (30 seconds for device 1)
1428 do {
1429 // Wait for Busy to drop.
1430 AtapiStallExecution(100);
1431 GetStatus(chan, statusByte);
1432 if(statusByte == IDE_STATUS_WRONG) {
1433 KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_WRONG (dev %d)\n", DeviceNumber));
1434 return FALSE;
1435 }
1436
1437 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
1438 GetBaseStatus(chan, statusByte2);
1439
1440 SelectDrive(chan, DeviceNumber);
1441 } else {
1442 GetBaseStatus(chan, statusByte2);
1443 }
1444 // Another check for signature, to deal with one model Atapi that doesn't assert signature after
1445 // a soft reset.
1446 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1447 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1448
1449 if (signatureLow == ATAPI_MAGIC_LSB &&
1450 signatureHigh == ATAPI_MAGIC_MSB) {
1451 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (2) (dev %d)\n", DeviceNumber));
1452 // Device is Atapi.
1453 return FALSE;
1454 }
1455
1456 statusByte = UniataIsIdle(deviceExtension, statusByte) & ~IDE_STATUS_INDEX;
1457 if (statusByte != IDE_STATUS_IDLE) {
1458 // Give up on this.
1459 KdPrint2((PRINT_PREFIX "IssueIdentify: no dev (dev %d)\n", DeviceNumber));
1460 return FALSE;
1461 }
1462 }
1463 } else {
1464 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI. Status (%#x)\n", statusByte));
1465 if(statusByte == IDE_STATUS_WRONG) {
1466 return FALSE;
1467 }
1468 //if(!(deviceExtension->HwFlags & UNIATA_SATA)) {
1469 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1470 statusByte = WaitForIdleLong(chan);
1471 KdPrint2((PRINT_PREFIX "IssueIdentify: Checking for ATAPI (2). Status (%#x)\n", statusByte));
1472 }
1473 atapiDev = TRUE;
1474 }
1475
1476 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1477 if(use_ahci) {
1478 statusByte = UniataAhciSendPIOCommand(HwDeviceExtension, lChannel, DeviceNumber,
1479 (PSCSI_REQUEST_BLOCK)NULL,
1480 (PUCHAR)(&deviceExtension->FullIdentifyData),
1481 DEV_BSIZE,
1482 Command,
1483 0, 0,
1484 0,
1485 0 /* ahci flags */ ,
1486 ATA_WAIT_INTR,
1487 1000 /* timeout 1 sec */
1488 );
1489 j = 9; // AHCI is rather different, skip loop at all
1490 } else
1491 if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
1492 j = 9; // don't send IDENTIFY, assume it is not supported
1493 KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS\n"));
1494 RtlZeroMemory(&(deviceExtension->FullIdentifyData), sizeof(deviceExtension->FullIdentifyData));
1495 RtlCopyMemory(&(deviceExtension->FullIdentifyData), &(LunExt->IdentifyData), sizeof(LunExt->IdentifyData));
1496 } else
1497 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
1498 j = 4; // skip old-style checks
1499 } else {
1500 j = 0;
1501 }
1502 for (; j < 4*2; j++) {
1503 // Send IDENTIFY command.
1504
1505 // Load CylinderHigh and CylinderLow with number bytes to transfer for old devices, use 0 for newer.
1506
1507 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, Command, (j < 4) ? DEV_BSIZE : 0 /* cyl */, 0, 0, 0, 0, ATA_WAIT_INTR);
1508 // Clear interrupt
1509
1510 if (statusByte & IDE_STATUS_DRQ) {
1511 // Read status to acknowledge any interrupts generated.
1512 KdPrint2((PRINT_PREFIX "IssueIdentify: IDE_STATUS_DRQ (%#x)\n", statusByte));
1513 GetBaseStatus(chan, statusByte);
1514 // One last check for Atapi.
1515 if (Command == IDE_COMMAND_IDENTIFY) {
1516 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1517 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1518
1519 if (signatureLow == ATAPI_MAGIC_LSB &&
1520 signatureHigh == ATAPI_MAGIC_MSB) {
1521 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (3) (dev %d)\n", DeviceNumber));
1522 // Device is Atapi.
1523 return FALSE;
1524 }
1525 }
1526 break;
1527 } else {
1528 KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (%#x)\n", statusByte));
1529 if (Command == IDE_COMMAND_IDENTIFY) {
1530 // Check the signature. If DRQ didn't come up it's likely Atapi.
1531 signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
1532 signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
1533
1534 if (signatureLow == ATAPI_MAGIC_LSB &&
1535 signatureHigh == ATAPI_MAGIC_MSB) {
1536 // Device is Atapi.
1537 KdPrint2((PRINT_PREFIX "IssueIdentify: this is ATAPI (4) (dev %d)\n", DeviceNumber));
1538 return FALSE;
1539 }
1540 } else {
1541 if(!(statusByte & IDE_STATUS_ERROR) && (statusByte & IDE_STATUS_BUSY)) {
1542 KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ not asserted immediately, BUSY -> WaitForDrq\n"));
1543 break;
1544 }
1545 }
1546 // Device didn't respond correctly. It will be given one more chance.
1547 KdPrint2((PRINT_PREFIX "IssueIdentify: DRQ never asserted (%#x). Error reg (%#x)\n",
1548 statusByte, AtapiReadPort1(chan, IDX_IO1_i_Error)));
1549 GetBaseStatus(chan, statusByte);
1550 AtapiSoftReset(chan,DeviceNumber);
1551
1552 AtapiDisableInterrupts(deviceExtension, lChannel);
1553 AtapiEnableInterrupts(deviceExtension, lChannel);
1554
1555 GetBaseStatus(chan, statusByte);
1556 //GetStatus(chan, statusByte);
1557 KdPrint2((PRINT_PREFIX "IssueIdentify: Status after soft reset (%#x)\n", statusByte));
1558 }
1559 }
1560 // Check for error on really stupid master devices that assert random
1561 // patterns of bits in the status register at the slave address.
1562 if ((Command == IDE_COMMAND_IDENTIFY) && (statusByte & IDE_STATUS_ERROR)) {
1563 KdPrint2((PRINT_PREFIX "IssueIdentify: Exit on error (%#x)\n", statusByte));
1564 return FALSE;
1565 }
1566
1567 if(use_ahci) {
1568 // everything should already be done by controller
1569 } else
1570 if(LunExt->DeviceFlags & DFLAGS_MANUAL_CHS) {
1571 j = 9; // don't send IDENTIFY, assume it is not supported
1572 KdPrint2((PRINT_PREFIX "IssueIdentify: Manual CHS (2)\n"));
1573 statusByte = WaitForDrq(chan);
1574 statusByte = WaitOnBusyLong(chan);
1575 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1576 GetBaseStatus(chan, statusByte);
1577 } else {
1578
1579 KdPrint2((PRINT_PREFIX "IssueIdentify: Status before read words %#x\n", statusByte));
1580 // Suck out 256 words. After waiting for one model that asserts busy
1581 // after receiving the Packet Identify command.
1582 statusByte = WaitForDrq(chan);
1583 statusByte = WaitOnBusyLong(chan);
1584 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1585
1586 if (!(statusByte & IDE_STATUS_DRQ)) {
1587 KdPrint2((PRINT_PREFIX "IssueIdentify: !IDE_STATUS_DRQ (2) (%#x)\n", statusByte));
1588 GetBaseStatus(chan, statusByte);
1589 return FALSE;
1590 }
1591 GetBaseStatus(chan, statusByte);
1592 KdPrint2((PRINT_PREFIX "IssueIdentify: BASE statusByte %#x\n", statusByte));
1593
1594 if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
1595
1596 KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
1597
1598 // ATI/SII chipsets with memory-mapped IO hangs when
1599 // I call ReadBuffer(), probably due to PCI burst/prefetch enabled
1600 // Unfortunately, I don't know yet how to workaround it except
1601 // spacifying manual delay in the way you see below.
1602 ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
1603
1604 // Work around for some IDE and one model Atapi that will present more than
1605 // 256 bytes for the Identify data.
1606 KdPrint2((PRINT_PREFIX "IssueIdentify: suck data port\n", statusByte));
1607 statusByte = AtapiSuckPort2(chan);
1608 } else {
1609 KdPrint2((PRINT_PREFIX " use 32bit IO\n"));
1610 ReadBuffer2(chan, (PULONG)&deviceExtension->FullIdentifyData, 256/2, PIO0_TIMING);
1611 }
1612
1613 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1614 statusByte = WaitForDrq(chan);
1615 KdPrint2((PRINT_PREFIX "IssueIdentify: statusByte %#x\n", statusByte));
1616 GetBaseStatus(chan, statusByte);
1617 }
1618 KdPrint2((PRINT_PREFIX "IssueIdentify: Status after read words %#x\n", statusByte));
1619
1620 if(NoSetup) {
1621 KdPrint2((PRINT_PREFIX "IssueIdentify: no setup, exiting\n"));
1622 return TRUE;
1623 }
1624
1625 KdPrint2((PRINT_PREFIX "Model: %20.20s\n", deviceExtension->FullIdentifyData.ModelNumber));
1626 KdPrint2((PRINT_PREFIX "FW: %4.4s\n", deviceExtension->FullIdentifyData.FirmwareRevision));
1627 KdPrint2((PRINT_PREFIX "S/N: %20.20s\n", deviceExtension->FullIdentifyData.SerialNumber));
1628 KdPrint2((PRINT_PREFIX "Pio: %x\n", deviceExtension->FullIdentifyData.PioCycleTimingMode));
1629 if(deviceExtension->FullIdentifyData.PioTimingsValid) {
1630 KdPrint2((PRINT_PREFIX "APio: %x\n", deviceExtension->FullIdentifyData.AdvancedPIOModes));
1631 }
1632 KdPrint2((PRINT_PREFIX "SWDMA: %x\n", deviceExtension->FullIdentifyData.SingleWordDMAActive));
1633 KdPrint2((PRINT_PREFIX "MWDMA: %x\n", deviceExtension->FullIdentifyData.MultiWordDMAActive));
1634 if(deviceExtension->FullIdentifyData.UdmaModesValid) {
1635 KdPrint2((PRINT_PREFIX "UDMA: %x/%x\n", deviceExtension->FullIdentifyData.UltraDMAActive, deviceExtension->FullIdentifyData.UltraDMASupport));
1636 }
1637 KdPrint2((PRINT_PREFIX "SATA: %x\n", deviceExtension->FullIdentifyData.SataEnable));
1638 KdPrint2((PRINT_PREFIX "SATA support: %x, CAPs %#x\n",
1639 deviceExtension->FullIdentifyData.SataSupport,
1640 deviceExtension->FullIdentifyData.SataCapabilities));
1641
1642 LunExt->LimitedTransferMode =
1643 LunExt->OrigTransferMode =
1644 (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_MAX);
1645 LunExt->TransferMode =
1646 (UCHAR)ata_cur_mode_from_ident(&(deviceExtension->FullIdentifyData), IDENT_MODE_ACTIVE);
1647
1648 KdPrint2((PRINT_PREFIX "OrigTransferMode: %x, Active: %x\n", LunExt->OrigTransferMode, LunExt->TransferMode));
1649 KdPrint2((PRINT_PREFIX "Accoustic %d, cur %d\n",
1650 deviceExtension->FullIdentifyData.VendorAcoustic,
1651 deviceExtension->FullIdentifyData.CurrentAcoustic
1652 ));
1653 KdPrint2((PRINT_PREFIX "AdvPowerMode %d, cur %d\n",
1654 deviceExtension->FullIdentifyData.CfAdvPowerMode
1655 ));
1656
1657 // Check out a few capabilities / limitations of the device.
1658 if (deviceExtension->FullIdentifyData.RemovableStatus & 1) {
1659 // Determine if this drive supports the MSN functions.
1660 KdPrint2((PRINT_PREFIX "IssueIdentify: Marking drive %d as removable. SFE = %d\n",
1661 DeviceNumber,
1662 deviceExtension->FullIdentifyData.RemovableStatus));
1663 LunExt->DeviceFlags |= DFLAGS_REMOVABLE_DRIVE;
1664 }
1665 if(use_ahci) {
1666 // AHCI doesn't recommend using PIO and multiblock
1667 LunExt->MaximumBlockXfer = 0;
1668 } else
1669 if (deviceExtension->FullIdentifyData.MaximumBlockTransfer) {
1670 // Determine max. block transfer for this device.
1671 LunExt->MaximumBlockXfer =
1672 (UCHAR)(deviceExtension->FullIdentifyData.MaximumBlockTransfer & 0xFF);
1673 }
1674 LunExt->NumOfSectors = 0;
1675 if (Command == IDE_COMMAND_IDENTIFY) {
1676 ULONGLONG NumOfSectors=0;
1677 ULONGLONG NativeNumOfSectors=0;
1678 ULONGLONG cylinders=0;
1679 ULONGLONG tmp_cylinders=0;
1680 // Read very-old-style drive geometry
1681 KdPrint2((PRINT_PREFIX "CHS %#x:%#x:%#x\n",
1682 deviceExtension->FullIdentifyData.NumberOfCylinders,
1683 deviceExtension->FullIdentifyData.NumberOfHeads,
1684 deviceExtension->FullIdentifyData.SectorsPerTrack
1685 ));
1686 NumOfSectors = deviceExtension->FullIdentifyData.NumberOfCylinders *
1687 deviceExtension->FullIdentifyData.NumberOfHeads *
1688 deviceExtension->FullIdentifyData.SectorsPerTrack;
1689 KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1690 // Check for HDDs > 8Gb
1691 if ((deviceExtension->FullIdentifyData.NumberOfCylinders == 0x3fff) &&
1692 /* (deviceExtension->FullIdentifyData.TranslationFieldsValid) &&*/
1693 (NumOfSectors < deviceExtension->FullIdentifyData.UserAddressableSectors)) {
1694 KdPrint2((PRINT_PREFIX "NumberOfCylinders == 0x3fff\n"));
1695 cylinders =
1696 (deviceExtension->FullIdentifyData.UserAddressableSectors /
1697 (deviceExtension->FullIdentifyData.NumberOfHeads *
1698 deviceExtension->FullIdentifyData.SectorsPerTrack));
1699
1700 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
1701
1702 NumOfSectors = cylinders *
1703 deviceExtension->FullIdentifyData.NumberOfHeads *
1704 deviceExtension->FullIdentifyData.SectorsPerTrack;
1705
1706 KdPrint2((PRINT_PREFIX "NumOfSectors %#I64x\n", NumOfSectors));
1707 } else {
1708
1709 }
1710 // Check for LBA mode
1711 KdPrint2((PRINT_PREFIX "SupportLba flag %#x\n", deviceExtension->FullIdentifyData.SupportLba));
1712 KdPrint2((PRINT_PREFIX "MajorRevision %#x\n", deviceExtension->FullIdentifyData.MajorRevision));
1713 KdPrint2((PRINT_PREFIX "UserAddressableSectors %#x\n", deviceExtension->FullIdentifyData.UserAddressableSectors));
1714 if ( deviceExtension->FullIdentifyData.SupportLba
1715 ||
1716 (deviceExtension->FullIdentifyData.MajorRevision &&
1717 /* deviceExtension->FullIdentifyData.TranslationFieldsValid &&*/
1718 deviceExtension->FullIdentifyData.UserAddressableSectors)) {
1719 KdPrint2((PRINT_PREFIX "LBA mode\n"));
1720 LunExt->DeviceFlags |= DFLAGS_LBA_ENABLED;
1721 } else {
1722 KdPrint2((PRINT_PREFIX "Keep orig geometry\n"));
1723 LunExt->DeviceFlags |= DFLAGS_ORIG_GEOMETRY;
1724 goto skip_lba_staff;
1725 }
1726 // Check for LBA48 support
1727 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
1728 if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48 &&
1729 deviceExtension->FullIdentifyData.FeaturesEnabled.Address48 &&
1730 (deviceExtension->FullIdentifyData.UserAddressableSectors48 > NumOfSectors)
1731 ) {
1732 KdPrint2((PRINT_PREFIX "LBA48\n"));
1733 cylinders =
1734 (deviceExtension->FullIdentifyData.UserAddressableSectors48 /
1735 (deviceExtension->FullIdentifyData.NumberOfHeads *
1736 deviceExtension->FullIdentifyData.SectorsPerTrack));
1737
1738 KdPrint2((PRINT_PREFIX "cylinders %#I64x\n", cylinders));
1739
1740 NativeNumOfSectors = cylinders *
1741 deviceExtension->FullIdentifyData.NumberOfHeads *
1742 deviceExtension->FullIdentifyData.SectorsPerTrack;
1743
1744 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
1745
1746 if(NativeNumOfSectors > NumOfSectors) {
1747 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
1748 NumOfSectors = NativeNumOfSectors;
1749 }
1750 }
1751
1752 // Check drive capacity report for LBA48-capable drives.
1753 if(deviceExtension->FullIdentifyData.FeaturesSupport.Address48) {
1754 ULONG hNativeNumOfSectors;
1755 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE48\n"));
1756
1757 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1758 IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
1759
1760 if(!(statusByte & IDE_STATUS_ERROR)) {
1761 if(use_ahci) {
1762 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
1763 } else {
1764 NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
1765 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
1766 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) ;
1767
1768 AtapiWritePort1(chan, IDX_IO2_o_Control,
1769 IDE_DC_USE_HOB );
1770
1771 KdPrint2((PRINT_PREFIX "Read high order bytes\n"));
1772 NativeNumOfSectors |=
1773 (ULONG)((ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24 );
1774 hNativeNumOfSectors=
1775 (ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) |
1776 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 8) ;
1777 ((PULONG)&NativeNumOfSectors)[1] = hNativeNumOfSectors;
1778 }
1779 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
1780
1781 // Some drives report LBA48 capability while has capacity below 128Gb
1782 // Probably they support large block-counters.
1783 // But the problem is that some of them reports higher part of Max LBA equal to lower part.
1784 // Here we check this
1785 if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
1786 KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!!\n"));
1787
1788 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1789 IDE_COMMAND_READ_NATIVE_SIZE48, 0, 0, 0, ATA_WAIT_READY);
1790
1791 if(!(statusByte & IDE_STATUS_ERROR)) {
1792 if(use_ahci) {
1793 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
1794 } else {
1795 NativeNumOfSectors = (ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
1796 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) << 24) |
1797 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8 ) |
1798 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 32) |
1799 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
1800 ((ULONGLONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 40)
1801 ;
1802 }
1803 }
1804
1805 if((NativeNumOfSectors & 0xffffff) == ((NativeNumOfSectors >> 24) & 0xffffff)) {
1806 KdPrint2((PRINT_PREFIX "High-order bytes == Low-order bytes !!! (2)\n"));
1807 NativeNumOfSectors = 0;
1808 }
1809 }
1810
1811 if(NumOfSectors <= ATA_MAX_LBA28 &&
1812 NativeNumOfSectors > NumOfSectors) {
1813
1814 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE48\n"));
1815 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
1816
1817 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1818 IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
1819 if(!(statusByte & IDE_STATUS_ERROR)) {
1820 NumOfSectors = NativeNumOfSectors;
1821 }
1822 }
1823 } // !error
1824 }
1825
1826 if(NumOfSectors < 0x2100000 /*&& NumOfSectors > 31*1000*1000*/) {
1827 // check for native LBA size
1828 // some drives report ~32Gb in Identify Block
1829 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_READ_NATIVE_SIZE\n"));
1830
1831 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_READ_NATIVE_SIZE,
1832 0, IDE_USE_LBA, 0, 0, 0, ATA_WAIT_READY);
1833
1834 if(!(statusByte & IDE_STATUS_ERROR)) {
1835 if(use_ahci) {
1836 NativeNumOfSectors = chan->AhciInternalAtaReq->ahci.in_lba;
1837 } else {
1838 NativeNumOfSectors = (ULONG)AtapiReadPort1(chan, IDX_IO1_i_BlockNumber) |
1839 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) << 8) |
1840 ((ULONG)AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh) << 16) |
1841 (((ULONG)AtapiReadPort1(chan, IDX_IO1_i_DriveSelect) & 0xf) << 24);
1842 }
1843 KdPrint2((PRINT_PREFIX "NativeNumOfSectors %#I64x\n", NativeNumOfSectors));
1844
1845 if(NativeNumOfSectors > NumOfSectors) {
1846
1847 KdPrint2((PRINT_PREFIX "Use IDE_COMMAND_SET_NATIVE_SIZE\n"));
1848 KdPrint2((PRINT_PREFIX "Update NumOfSectors to %#I64x\n", NativeNumOfSectors));
1849
1850 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
1851 IDE_COMMAND_SET_NATIVE_SIZE, NativeNumOfSectors, 0, 0, ATA_WAIT_READY);
1852 if(!(statusByte & IDE_STATUS_ERROR)) {
1853 NumOfSectors = NativeNumOfSectors;
1854 }
1855 }
1856 }
1857 }
1858
1859 } // if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED)
1860
1861 // fill IdentifyData with bogus geometry
1862 KdPrint2((PRINT_PREFIX "requested LunExt->GeomType=%x\n", LunExt->opt_GeomType));
1863 tmp_cylinders = NumOfSectors / (deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *
1864 deviceExtension->FullIdentifyData.NumberOfCurrentHeads);
1865 KdPrint2((PRINT_PREFIX "tmp_cylinders = %#I64x\n", tmp_cylinders));
1866 if((tmp_cylinders < 0xffff) || (LunExt->opt_GeomType == GEOM_ORIG)) {
1867 // ok, we can keep original values
1868 if(LunExt->opt_GeomType == GEOM_AUTO) {
1869 LunExt->opt_GeomType = GEOM_ORIG;
1870 }
1871 } else {
1872 tmp_cylinders = NumOfSectors / (255*63);
1873 if(tmp_cylinders < 0xffff) {
1874 // we can use generic values for H/S for generic geometry approach
1875 if(LunExt->opt_GeomType == GEOM_AUTO) {
1876 LunExt->opt_GeomType = GEOM_STD;
1877 }
1878 } else {
1879 // we should use UNIATA geometry approach
1880 if(LunExt->opt_GeomType == GEOM_AUTO) {
1881 LunExt->opt_GeomType = GEOM_UNIATA;
1882 }
1883 }
1884 }
1885
1886 if(LunExt->opt_GeomType == GEOM_STD) {
1887 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack =
1888 deviceExtension->FullIdentifyData.SectorsPerTrack = 63;
1889
1890 deviceExtension->FullIdentifyData.NumberOfCurrentHeads =
1891 deviceExtension->FullIdentifyData.NumberOfHeads = 255;
1892
1893 cylinders = NumOfSectors / (255*63);
1894 KdPrint2((PRINT_PREFIX "Use GEOM_STD, CHS=%I64x/%x/%x\n", cylinders, 255, 63));
1895 } else
1896 if(LunExt->opt_GeomType == GEOM_UNIATA) {
1897 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x80)) {
1898 cylinders /= 2;
1899 KdPrint2((PRINT_PREFIX "cylinders /= 2\n"));
1900 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
1901 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
1902 }
1903 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x80)) {
1904 cylinders /= 2;
1905 KdPrint2((PRINT_PREFIX "cylinders /= 2 (2)\n"));
1906 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
1907 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
1908 }
1909 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.SectorsPerTrack < 0x8000)) {
1910 cylinders /= 2;
1911 KdPrint2((PRINT_PREFIX "cylinders /= 2 (3)\n"));
1912 deviceExtension->FullIdentifyData.SectorsPerTrack *= 2;
1913 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack *= 2;
1914 }
1915 while ((cylinders > 0xffff) && (deviceExtension->FullIdentifyData.NumberOfHeads < 0x8000)) {
1916 cylinders /= 2;
1917 KdPrint2((PRINT_PREFIX "cylinders /= 2 (4)\n"));
1918 deviceExtension->FullIdentifyData.NumberOfHeads *= 2;
1919 deviceExtension->FullIdentifyData.NumberOfCurrentHeads *= 2;
1920 }
1921 KdPrint2((PRINT_PREFIX "Use GEOM_UNIATA, CHS=%I64x/%x/%x\n", cylinders,
1922 deviceExtension->FullIdentifyData.NumberOfCurrentHeads,
1923 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack));
1924 }
1925 if(!cylinders) {
1926 KdPrint2((PRINT_PREFIX "cylinders = tmp_cylinders (%x = %x)\n", cylinders, tmp_cylinders));
1927 cylinders = tmp_cylinders;
1928 }
1929 deviceExtension->FullIdentifyData.NumberOfCurrentCylinders =
1930 deviceExtension->FullIdentifyData.NumberOfCylinders = (USHORT)cylinders;
1931
1932 skip_lba_staff:
1933
1934 KdPrint2((PRINT_PREFIX "Geometry: C %#x (%#x)\n",
1935 deviceExtension->FullIdentifyData.NumberOfCylinders,
1936 deviceExtension->FullIdentifyData.NumberOfCurrentCylinders
1937 ));
1938 KdPrint2((PRINT_PREFIX "Geometry: H %#x (%#x)\n",
1939 deviceExtension->FullIdentifyData.NumberOfHeads,
1940 deviceExtension->FullIdentifyData.NumberOfCurrentHeads
1941 ));
1942 KdPrint2((PRINT_PREFIX "Geometry: S %#x (%#x)\n",
1943 deviceExtension->FullIdentifyData.SectorsPerTrack,
1944 deviceExtension->FullIdentifyData.CurrentSectorsPerTrack
1945 ));
1946
1947 if(NumOfSectors)
1948 LunExt->NumOfSectors = NumOfSectors;
1949 /* if(deviceExtension->FullIdentifyData.MajorRevision &&
1950 deviceExtension->FullIdentifyData.DoubleWordIo) {
1951 LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
1952 }*/
1953 }
1954
1955 ScsiPortMoveMemory(&LunExt->IdentifyData,
1956 &deviceExtension->FullIdentifyData,sizeof(IDENTIFY_DATA2));
1957
1958 InitBadBlocks(LunExt);
1959
1960 if ((LunExt->IdentifyData.DrqType & ATAPI_DRQT_INTR) &&
1961 (Command != IDE_COMMAND_IDENTIFY)) {
1962
1963 // This device interrupts with the assertion of DRQ after receiving
1964 // Atapi Packet Command
1965 LunExt->DeviceFlags |= DFLAGS_INT_DRQ;
1966 KdPrint2((PRINT_PREFIX "IssueIdentify: Device interrupts on assertion of DRQ.\n"));
1967
1968 } else {
1969 KdPrint2((PRINT_PREFIX "IssueIdentify: Device does not interrupt on assertion of DRQ.\n"));
1970 }
1971
1972 if(Command != IDE_COMMAND_IDENTIFY) {
1973 // ATAPI branch
1974 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_TAPE) {
1975 // This is a tape.
1976 LunExt->DeviceFlags |= DFLAGS_TAPE_DEVICE;
1977 KdPrint2((PRINT_PREFIX "IssueIdentify: Device is a tape drive.\n"));
1978 } else
1979 if(LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM ||
1980 LunExt->IdentifyData.DeviceType == ATAPI_TYPE_OPTICAL) {
1981 KdPrint2((PRINT_PREFIX "IssueIdentify: Device is CD/Optical drive.\n"));
1982 // set CD default costs
1983 LunExt->RwSwitchCost = REORDER_COST_SWITCH_RW_CD;
1984 LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD;
1985 LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD;
1986 statusByte = WaitForDrq(chan);
1987 } else {
1988 KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n",
1989 LunExt->IdentifyData.DeviceType));
1990 }
1991 } else {
1992 KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n"));
1993 }
1994
1995 GetBaseStatus(chan, statusByte);
1996 KdPrint2((PRINT_PREFIX "IssueIdentify: final Status on exit (%#x)\n", statusByte));
1997 return TRUE;
1998
1999 } // end IssueIdentify()
2000
2001
2002 /*++
2003
2004 Routine Description:
2005 Set drive parameters using the IDENTIFY data.
2006
2007 Arguments:
2008 HwDeviceExtension - HBA miniport driver's adapter data storage
2009 DeviceNumber - Indicates which device.
2010
2011 Return Value:
2012 TRUE if all goes well.
2013
2014 --*/
2015 BOOLEAN
2016 NTAPI
2017 SetDriveParameters(
2018 IN PVOID HwDeviceExtension,
2019 IN ULONG DeviceNumber,
2020 IN ULONG lChannel
2021 )
2022 {
2023 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2024 PIDENTIFY_DATA2 identifyData;
2025 PHW_LU_EXTENSION LunExt;
2026 // ULONG i;
2027 UCHAR statusByte;
2028 UCHAR errorByte;
2029
2030 LunExt = deviceExtension->chan[lChannel].lun[DeviceNumber];
2031 identifyData = &(LunExt->IdentifyData);
2032
2033 if(LunExt->DeviceFlags &
2034 (DFLAGS_LBA_ENABLED | DFLAGS_ORIG_GEOMETRY))
2035 return TRUE;
2036
2037 KdPrint2((PRINT_PREFIX "SetDriveParameters: Number of heads %#x\n", identifyData->NumberOfHeads));
2038 KdPrint2((PRINT_PREFIX "SetDriveParameters: Sectors per track %#x\n", identifyData->SectorsPerTrack));
2039
2040 // Send SET PARAMETER command.
2041 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
2042 IDE_COMMAND_SET_DRIVE_PARAMETERS, 0,
2043 (identifyData->NumberOfHeads - 1), 0,
2044 (UCHAR)identifyData->SectorsPerTrack, 0, ATA_WAIT_IDLE);
2045
2046 statusByte = UniataIsIdle(deviceExtension, statusByte);
2047 if(statusByte & IDE_STATUS_ERROR) {
2048 errorByte = AtapiReadPort1(&deviceExtension->chan[lChannel], IDX_IO1_i_Error);
2049 KdPrint2((PRINT_PREFIX "SetDriveParameters: Error bit set. Status %#x, error %#x\n",
2050 errorByte, statusByte));
2051 return FALSE;
2052 }
2053
2054 if(statusByte == IDE_STATUS_IDLE) {
2055 return TRUE;
2056 }
2057
2058 return FALSE;
2059
2060 } // end SetDriveParameters()
2061
2062 VOID
2063 NTAPI
2064 UniataForgetDevice(
2065 PHW_LU_EXTENSION LunExt
2066 )
2067 {
2068 // keep only DFLAGS_HIDDEN flag
2069 LunExt->DeviceFlags &= DFLAGS_HIDDEN;
2070 LunExt->AtapiReadyWaitDelay = 0;
2071 } // end UniataForgetDevice()
2072
2073
2074 /*++
2075
2076 Routine Description:
2077 Reset IDE controller and/or Atapi device.
2078 ->HwResetBus
2079
2080 Arguments:
2081 HwDeviceExtension - HBA miniport driver's adapter data storage
2082
2083 Return Value:
2084 Nothing.
2085
2086
2087 --*/
2088 BOOLEAN
2089 NTAPI
2090 AtapiResetController(
2091 IN PVOID HwDeviceExtension,
2092 IN ULONG PathId
2093 )
2094 {
2095 KdPrint2((PRINT_PREFIX "AtapiResetController(%x)\n", PathId));
2096 return AtapiResetController__(HwDeviceExtension, PathId, RESET_COMPLETE_ALL);
2097 } // end AtapiResetController()
2098
2099 BOOLEAN
2100 NTAPI
2101 AtapiResetController__(
2102 IN PVOID HwDeviceExtension,
2103 IN ULONG PathId,
2104 IN BOOLEAN CompleteType
2105 )
2106 {
2107 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2108 ULONG numberChannels = deviceExtension->NumberChannels;
2109 PHW_CHANNEL chan = NULL;
2110 ULONG i,j;
2111 ULONG MaxLuns;
2112 UCHAR statusByte;
2113 PSCSI_REQUEST_BLOCK CurSrb;
2114 ULONG ChannelCtrlFlags;
2115 UCHAR dma_status = 0;
2116
2117 ULONG slotNumber = deviceExtension->slotNumber;
2118 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
2119 ULONG VendorID = deviceExtension->DevID & 0xffff;
2120 #ifdef _DEBUG
2121 ULONG DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
2122 #endif
2123 //ULONG RevID = deviceExtension->RevID;
2124 ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
2125 //UCHAR tmp8;
2126 UCHAR tmp16;
2127
2128 KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber));
2129 KdPrint2((PRINT_PREFIX "simplexOnly %d\n", deviceExtension->simplexOnly));
2130
2131 if(!deviceExtension->simplexOnly && (PathId != CHAN_NOT_SPECIFIED)) {
2132 // we shall reset both channels on SimplexOnly devices,
2133 // It's not worth doing so on normal controllers
2134 j = PathId;
2135 numberChannels = min(j+1, deviceExtension->NumberChannels);
2136 } else {
2137 j=0;
2138 numberChannels = deviceExtension->NumberChannels;
2139 }
2140
2141 for (; j < numberChannels; j++) {
2142
2143 KdPrint2((PRINT_PREFIX "AtapiResetController: Reset channel %d\n", j));
2144 chan = &(deviceExtension->chan[j]);
2145 MaxLuns = chan->NumberLuns;
2146 KdPrint2((PRINT_PREFIX " CompleteType %#x, Luns %d, chan %#x, sptr %#x\n", CompleteType, MaxLuns, chan, &chan));
2147 //MaxLuns = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : 2;
2148 if(CompleteType != RESET_COMPLETE_NONE) {
2149 #ifndef UNIATA_CORE
2150 while((CurSrb = UniataGetCurRequest(chan))) {
2151
2152 PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
2153
2154 KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb, chan));
2155 // Check and see if we are processing an internal srb
2156 if (AtaReq->OriginalSrb) {
2157 KdPrint2((PRINT_PREFIX " restore original SRB %#x\n", AtaReq->OriginalSrb));
2158 AtaReq->Srb = AtaReq->OriginalSrb;
2159 CurSrb->SrbExtension = NULL;
2160 AtaReq->OriginalSrb = NULL;
2161 // NOTE: internal SRB doesn't get to SRB queue !!!
2162 CurSrb = AtaReq->Srb;
2163 }
2164
2165 // Remove current request from queue
2166 UniataRemoveRequest(chan, CurSrb);
2167
2168 // Check if request is in progress.
2169 ASSERT(AtaReq->Srb == CurSrb);
2170 if (CurSrb) {
2171 // Complete outstanding request with SRB_STATUS_BUS_RESET.
2172 UCHAR PathId = CurSrb->PathId;
2173 UCHAR TargetId = CurSrb->TargetId;
2174 UCHAR Lun = CurSrb->Lun;
2175
2176 CurSrb->SrbStatus = ((CompleteType == RESET_COMPLETE_ALL) ? SRB_STATUS_BUS_RESET : SRB_STATUS_ABORTED) | SRB_STATUS_AUTOSENSE_VALID;
2177 CurSrb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
2178
2179 if (CurSrb->SenseInfoBuffer) {
2180
2181 PSENSE_DATA senseBuffer = (PSENSE_DATA)CurSrb->SenseInfoBuffer;
2182 KdPrint2((PRINT_PREFIX " senseBuffer %#x, chan %#x\n", senseBuffer, chan));
2183
2184 senseBuffer->ErrorCode = 0x70;
2185 senseBuffer->Valid = 1;
2186 senseBuffer->AdditionalSenseLength = 0xb;
2187 if(CompleteType == RESET_COMPLETE_ALL) {
2188 KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_UNIT_ATTENTION + SCSI_ADSENSE_BUS_RESET\n"));
2189 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2190 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_BUS_RESET;
2191 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_SCSI_BUS;
2192 } else {
2193 KdPrint2((PRINT_PREFIX "AtapiResetController: report SCSI_SENSE_ABORTED_COMMAND\n"));
2194 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
2195 senseBuffer->AdditionalSenseCode = 0;
2196 senseBuffer->AdditionalSenseCodeQualifier = 0;
2197 }
2198 }
2199
2200 // Clear request tracking fields.
2201 AtaReq->WordsLeft = 0;
2202 AtaReq->DataBuffer = NULL;
2203 AtaReq->TransferLength = 0;
2204 KdPrint2((PRINT_PREFIX "chan %#x\n", chan));
2205
2206 ScsiPortNotification(RequestComplete,
2207 deviceExtension,
2208 CurSrb);
2209
2210 // Indicate ready for next request.
2211 ScsiPortNotification(NextLuRequest,
2212 deviceExtension,
2213 PathId,
2214 TargetId,
2215 Lun);
2216 }
2217 if(CompleteType != RESET_COMPLETE_ALL)
2218 break;
2219 } // end while()
2220 #endif //UNIATA_CORE
2221 } // end if (!CompleteType != RESET_COMPLETE_NONE)
2222
2223 // Save control flags
2224 ChannelCtrlFlags = chan->ChannelCtrlFlags;
2225 // Clear expecting interrupt flag.
2226 UniataExpectChannelInterrupt(chan, FALSE);
2227 chan->RDP = FALSE;
2228 chan->ChannelCtrlFlags = 0;
2229 InterlockedExchange(&(chan->CheckIntr),
2230 CHECK_INTR_IDLE);
2231
2232 for (i = 0; i < MaxLuns; i++) {
2233 chan->lun[i]->PowerState = 0;
2234 }
2235 // Reset controller
2236 if(ChipFlags & UNIATA_AHCI) {
2237 KdPrint2((PRINT_PREFIX " AHCI path\n"));
2238 if(UniataAhciChanImplemented(deviceExtension, j)) {
2239 #if DBG
2240 UniataDumpAhciPortRegs(chan);
2241 #endif
2242 AtapiDisableInterrupts(deviceExtension, j);
2243 UniataAhciReset(HwDeviceExtension, j);
2244 } else {
2245 KdPrint2((PRINT_PREFIX " skip not implemented\n"));
2246 }
2247 } else {
2248 KdPrint2((PRINT_PREFIX " ATA path, chan %#x\n", chan));
2249 KdPrint2((PRINT_PREFIX " disable intr (0)\n"));
2250 AtapiDisableInterrupts(deviceExtension, j);
2251 KdPrint2((PRINT_PREFIX " done\n"));
2252 switch(VendorID) {
2253 case ATA_INTEL_ID: {
2254 ULONG mask;
2255 ULONG pshift;
2256 ULONG timeout;
2257 if(!(ChipFlags & UNIATA_SATA)) {
2258 goto default_reset;
2259 }
2260 if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2261 goto default_reset;
2262 }
2263
2264 #if 0
2265 /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
2266 if(ChipFlags & UNIATA_AHCI) {
2267 mask = 0x0005 << j;
2268 } else {
2269 /* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
2270 GetPciConfig1(0x90, tmp8);
2271 if(tmp8 & 0x04) {
2272 mask = 0x0003;
2273 } else {
2274 mask = 0x0001 << j;
2275 }
2276 }
2277 #else
2278 mask = 1 << chan->lun[0]->SATA_lun_map;
2279 if (MaxLuns > 1) {
2280 mask |= (1 << chan->lun[1]->SATA_lun_map);
2281 }
2282 #endif
2283 ChangePciConfig2(0x92, a & ~mask);
2284 AtapiStallExecution(10);
2285 ChangePciConfig2(0x92, a | mask);
2286 timeout = 100;
2287
2288 /* Wait up to 1 sec for "connect well". */
2289 if (ChipFlags & (I6CH | I6CH2)) {
2290 pshift = 8;
2291 } else {
2292 pshift = 4;
2293 }
2294 while (timeout--) {
2295 GetPciConfig2(0x92, tmp16);
2296 if (((tmp16 >> pshift) & mask) == mask) {
2297 GetBaseStatus(chan, statusByte);
2298 if(statusByte != IDE_STATUS_WRONG) {
2299 break;
2300 }
2301 }
2302 AtapiStallExecution(10000);
2303 }
2304 break; }
2305 case ATA_SIS_ID:
2306 case ATA_NVIDIA_ID: {
2307 KdPrint2((PRINT_PREFIX " SIS/nVidia\n"));
2308 if(!(ChipFlags & UNIATA_SATA))
2309 goto default_reset;
2310 break; }
2311 case ATA_SILICON_IMAGE_ID: {
2312 ULONG offset;
2313 ULONG Channel = deviceExtension->Channel + j;
2314 if(!(ChipFlags & UNIATA_SATA))
2315 goto default_reset;
2316 offset = ((Channel & 1) << 7) + ((Channel & 2) << 8);
2317 /* disable PHY state change interrupt */
2318 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x148 + offset, 0);
2319
2320 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
2321
2322 /* reset controller part for this channel */
2323 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2324 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) | (0xc0 >> Channel));
2325 AtapiStallExecution(1000);
2326 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48,
2327 AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), 0x48) & ~(0xc0 >> Channel));
2328
2329
2330 break; }
2331 case ATA_PROMISE_ID: {
2332 break; }
2333 default:
2334 if(ChipFlags & UNIATA_SATA) {
2335 KdPrint2((PRINT_PREFIX " SATA generic reset\n"));
2336 UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0);
2337 }
2338 default_reset:
2339 KdPrint2((PRINT_PREFIX " send reset\n"));
2340 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS |
2341 IDE_DC_RESET_CONTROLLER );
2342 KdPrint2((PRINT_PREFIX " wait a little\n"));
2343 AtapiStallExecution(10000);
2344 // Disable interrupts
2345 KdPrint2((PRINT_PREFIX " disable intr\n"));
2346 AtapiDisableInterrupts(deviceExtension, j);
2347 AtapiStallExecution(100);
2348 KdPrint2((PRINT_PREFIX " re-enable intr\n"));
2349 AtapiEnableInterrupts(deviceExtension, j);
2350 KdPrint2((PRINT_PREFIX " wait a little (2)\n"));
2351 AtapiStallExecution(100000);
2352 KdPrint2((PRINT_PREFIX " done\n"));
2353
2354 break;
2355 } // end switch()
2356
2357 //if(!(ChipFlags & UNIATA_SATA)) {}
2358 if(!UniataIsSATARangeAvailable(deviceExtension, j)) {
2359 // Reset DMA engine if active
2360 KdPrint2((PRINT_PREFIX " check DMA engine\n"));
2361 dma_status = GetDmaStatus(chan->DeviceExtension, chan->lChannel);
2362 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
2363 if((ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
2364 (dma_status & BM_STATUS_INTR)) {
2365 AtapiDmaDone(HwDeviceExtension, 0, j, NULL);
2366 }
2367 }
2368 } // ATA vs AHCI
2369
2370 // all these shall be performed inside AtapiHwInitialize__() ?
2371 #if 1
2372 KdPrint2((PRINT_PREFIX " process connected devices 0 - %d\n", MaxLuns-1));
2373 // Do special processing for ATAPI and IDE disk devices.
2374 for (i = 0; i < MaxLuns; i++) {
2375
2376 // Check if device present.
2377 KdPrint2((PRINT_PREFIX " Chan %#x\n", chan));
2378 KdPrint2((PRINT_PREFIX " Lun %#x\n", i));
2379 KdPrint2((PRINT_PREFIX " Lun ptr %#x\n", chan->lun[i]));
2380 if (!(chan->lun[i]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
2381 if(ChipFlags & UNIATA_AHCI) {
2382 // everything is done in UniataAhciReset()
2383 KdPrint2((PRINT_PREFIX " device have gone\n"));
2384 continue;
2385 }
2386 #ifdef NAVO_TEST
2387 continue;
2388 #else //NAVO_TEST
2389 //if(!CheckDevice(HwDeviceExtension, i, j, FALSE))
2390 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2391 continue;
2392 }
2393 if(!CheckDevice(HwDeviceExtension, j, i, TRUE)) {
2394 continue;
2395 }
2396 } else {
2397 if(ChipFlags & UNIATA_AHCI) {
2398 // everything is done in UniataAhciReset()
2399 KdPrint2((PRINT_PREFIX " found some device\n"));
2400
2401 if(!IssueIdentify(HwDeviceExtension,
2402 i, j,
2403 ATAPI_DEVICE(chan, i) ?
2404 IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
2405 FALSE)) {
2406 KdPrint2((PRINT_PREFIX " identify failed !\n"));
2407 UniataForgetDevice(chan->lun[i]);
2408 }
2409 continue;
2410 }
2411 if(!UniataAnybodyHome(HwDeviceExtension, j, i)) {
2412 KdPrint2((PRINT_PREFIX " device have gone\n"));
2413 UniataForgetDevice(chan->lun[i]);
2414 }
2415 #endif //NAVO_TEST
2416 }
2417
2418 SelectDrive(chan, i);
2419 AtapiStallExecution(10);
2420 statusByte = WaitOnBusyLong(chan);
2421 statusByte = UniataIsIdle(deviceExtension, statusByte);
2422 if(statusByte == IDE_STATUS_WRONG) {
2423 KdPrint2((PRINT_PREFIX
2424 "no drive, status %#x\n",
2425 statusByte));
2426 UniataForgetDevice(chan->lun[i]);
2427 } else
2428 // Check for ATAPI disk.
2429 if (ATAPI_DEVICE(chan, i)) {
2430 // Issue soft reset and issue identify.
2431 GetStatus(chan, statusByte);
2432 KdPrint2((PRINT_PREFIX "AtapiResetController: Status before Atapi reset (%#x).\n",
2433 statusByte));
2434
2435 AtapiDisableInterrupts(deviceExtension, j);
2436 AtapiSoftReset(chan, i);
2437 AtapiEnableInterrupts(deviceExtension, j);
2438
2439 GetStatus(chan, statusByte);
2440
2441 if(statusByte == IDE_STATUS_SUCCESS) {
2442
2443 IssueIdentify(HwDeviceExtension,
2444 i, j,
2445 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
2446 } else {
2447
2448 KdPrint2((PRINT_PREFIX
2449 "AtapiResetController: Status after soft reset %#x\n",
2450 statusByte));
2451 }
2452 GetBaseStatus(chan, statusByte);
2453
2454 } else {
2455 // Issue identify and reinit after channel reset.
2456
2457 if (statusByte != IDE_STATUS_IDLE &&
2458 statusByte != IDE_STATUS_SUCCESS &&
2459 statusByte != IDE_STATUS_DRDY) {
2460 // result2 = FALSE;
2461 KdPrint2((PRINT_PREFIX "AtapiResetController: IdeHardReset failed\n"));
2462 } else
2463 if(!IssueIdentify(HwDeviceExtension,
2464 i, j,
2465 IDE_COMMAND_IDENTIFY, FALSE)) {
2466 // result2 = FALSE;
2467 KdPrint2((PRINT_PREFIX "AtapiResetController: IDE IssueIdentify failed\n"));
2468 } else
2469 // Set disk geometry parameters.
2470 if (!SetDriveParameters(HwDeviceExtension, i, j)) {
2471 KdPrint2((PRINT_PREFIX "AtapiResetController: SetDriveParameters failed\n"));
2472 }
2473 GetBaseStatus(chan, statusByte);
2474 }
2475 // force DMA mode reinit
2476 chan->lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
2477 }
2478 #endif //0
2479
2480 // Enable interrupts, note, we can have here recursive disable
2481 AtapiStallExecution(10);
2482 KdPrint2((PRINT_PREFIX "AtapiResetController: deviceExtension->chan[%d].DisableIntr %d -> 1\n",
2483 j,
2484 chan->DisableIntr));
2485 AtapiEnableInterrupts(deviceExtension, j);
2486
2487 // Call the HwInitialize routine to setup multi-block.
2488 AtapiHwInitialize__(deviceExtension, j);
2489 } // for(channel)
2490 ScsiPortNotification(NextRequest, deviceExtension, NULL);
2491
2492 return TRUE;
2493
2494 } // end AtapiResetController__()
2495
2496
2497 /*++
2498
2499 Routine Description:
2500 This routine maps ATAPI and IDE errors to specific SRB statuses.
2501
2502 Arguments:
2503 HwDeviceExtension - HBA miniport driver's adapter data storage
2504 Srb - IO request packet
2505
2506 Return Value:
2507 SRB status
2508
2509 --*/
2510 ULONG
2511 NTAPI
2512 MapError(
2513 IN PVOID HwDeviceExtension,
2514 IN PSCSI_REQUEST_BLOCK Srb
2515 )
2516 {
2517 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2518 ULONG lChannel = GET_CHANNEL(Srb);
2519 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
2520 // ULONG i;
2521 UCHAR errorByte = 0;
2522 UCHAR srbStatus = SRB_STATUS_SUCCESS;
2523 UCHAR scsiStatus;
2524 ULONG DeviceNumber = GET_CDEV(Srb);
2525 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
2526
2527 // Read the error register.
2528
2529 if(deviceExtension->HwFlags & UNIATA_AHCI) {
2530 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
2531 if(AtaReq) {
2532 errorByte = AtaReq->ahci.in_error;
2533 } else {
2534 }
2535 } else {
2536 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2537 }
2538 KdPrint2((PRINT_PREFIX
2539 "MapError: Error register is %#x\n",
2540 errorByte));
2541
2542 if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
2543
2544 switch (errorByte >> 4) {
2545 case SCSI_SENSE_NO_SENSE:
2546
2547 KdPrint2((PRINT_PREFIX
2548 "ATAPI: No sense information\n"));
2549 scsiStatus = SCSISTAT_CHECK_CONDITION;
2550 srbStatus = SRB_STATUS_ERROR;
2551 break;
2552
2553 case SCSI_SENSE_RECOVERED_ERROR:
2554
2555 KdPrint2((PRINT_PREFIX
2556 "ATAPI: Recovered error\n"));
2557 scsiStatus = 0;
2558 srbStatus = SRB_STATUS_SUCCESS;
2559 break;
2560
2561 case SCSI_SENSE_NOT_READY:
2562
2563 KdPrint2((PRINT_PREFIX
2564 "ATAPI: Device not ready\n"));
2565 scsiStatus = SCSISTAT_CHECK_CONDITION;
2566 srbStatus = SRB_STATUS_ERROR;
2567 break;
2568
2569 case SCSI_SENSE_MEDIUM_ERROR:
2570
2571 KdPrint2((PRINT_PREFIX
2572 "ATAPI: Media error\n"));
2573 scsiStatus = SCSISTAT_CHECK_CONDITION;
2574 srbStatus = SRB_STATUS_ERROR;
2575 break;
2576
2577 case SCSI_SENSE_HARDWARE_ERROR:
2578
2579 KdPrint2((PRINT_PREFIX
2580 "ATAPI: Hardware error\n"));
2581 scsiStatus = SCSISTAT_CHECK_CONDITION;
2582 srbStatus = SRB_STATUS_ERROR;
2583 break;
2584
2585 case SCSI_SENSE_ILLEGAL_REQUEST:
2586
2587 KdPrint2((PRINT_PREFIX
2588 "ATAPI: Illegal request\n"));
2589 scsiStatus = SCSISTAT_CHECK_CONDITION;
2590 srbStatus = SRB_STATUS_ERROR;
2591 break;
2592
2593 case SCSI_SENSE_UNIT_ATTENTION:
2594
2595 KdPrint2((PRINT_PREFIX
2596 "ATAPI: Unit attention\n"));
2597 scsiStatus = SCSISTAT_CHECK_CONDITION;
2598 srbStatus = SRB_STATUS_ERROR;
2599 break;
2600
2601 case SCSI_SENSE_DATA_PROTECT:
2602
2603 KdPrint2((PRINT_PREFIX
2604 "ATAPI: Data protect\n"));
2605 scsiStatus = SCSISTAT_CHECK_CONDITION;
2606 srbStatus = SRB_STATUS_ERROR;
2607 break;
2608
2609 case SCSI_SENSE_BLANK_CHECK:
2610
2611 KdPrint2((PRINT_PREFIX
2612 "ATAPI: Blank check\n"));
2613 scsiStatus = SCSISTAT_CHECK_CONDITION;
2614 srbStatus = SRB_STATUS_ERROR;
2615 break;
2616
2617 case SCSI_SENSE_ABORTED_COMMAND:
2618 KdPrint2((PRINT_PREFIX
2619 "Atapi: Command Aborted\n"));
2620 scsiStatus = SCSISTAT_CHECK_CONDITION;
2621 srbStatus = SRB_STATUS_ERROR;
2622 break;
2623
2624 default:
2625
2626 KdPrint2((PRINT_PREFIX
2627 "ATAPI: Invalid sense information\n"));
2628 scsiStatus = 0;
2629 srbStatus = SRB_STATUS_ERROR;
2630 break;
2631 }
2632
2633 } else {
2634
2635 scsiStatus = 0;
2636
2637 // Save errorByte,to be used by SCSIOP_REQUEST_SENSE.
2638 chan->ReturningMediaStatus = errorByte;
2639
2640 if (errorByte & IDE_ERROR_MEDIA_CHANGE_REQ) {
2641 KdPrint2((PRINT_PREFIX
2642 "IDE: Media change\n"));
2643 scsiStatus = SCSISTAT_CHECK_CONDITION;
2644 srbStatus = SRB_STATUS_ERROR;
2645
2646 if (Srb->SenseInfoBuffer) {
2647
2648 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2649
2650 senseBuffer->ErrorCode = 0x70;
2651 senseBuffer->Valid = 1;
2652 senseBuffer->AdditionalSenseLength = 0xb;
2653 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2654 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
2655 senseBuffer->AdditionalSenseCodeQualifier = 0;
2656
2657 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2658 }
2659
2660 } else if (errorByte & IDE_ERROR_COMMAND_ABORTED) {
2661 KdPrint2((PRINT_PREFIX
2662 "IDE: Command abort\n"));
2663 srbStatus = SRB_STATUS_ABORTED;
2664 scsiStatus = SCSISTAT_CHECK_CONDITION;
2665
2666 if (Srb->SenseInfoBuffer) {
2667
2668 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2669
2670 senseBuffer->ErrorCode = 0x70;
2671 senseBuffer->Valid = 1;
2672 senseBuffer->AdditionalSenseLength = 0xb;
2673 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
2674 senseBuffer->AdditionalSenseCode = 0;
2675 senseBuffer->AdditionalSenseCodeQualifier = 0;
2676
2677 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2678 }
2679
2680 LunExt->ErrorCount++;
2681
2682 } else if (errorByte & IDE_ERROR_END_OF_MEDIA) {
2683
2684 KdPrint2((PRINT_PREFIX
2685 "IDE: End of media\n"));
2686 scsiStatus = SCSISTAT_CHECK_CONDITION;
2687 srbStatus = SRB_STATUS_ERROR;
2688
2689 if (Srb->SenseInfoBuffer) {
2690
2691 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2692
2693 senseBuffer->ErrorCode = 0x70;
2694 senseBuffer->Valid = 1;
2695 senseBuffer->AdditionalSenseLength = 0xb;
2696 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2697 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIA_STATE;
2698 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_END_OF_MEDIUM;
2699 senseBuffer->EndOfMedia = 1;
2700
2701 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2702 }
2703
2704 if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
2705 LunExt->ErrorCount++;
2706 }
2707
2708 } else if (errorByte & IDE_ERROR_ILLEGAL_LENGTH) {
2709
2710 KdPrint2((PRINT_PREFIX
2711 "IDE: Illegal length\n"));
2712 srbStatus = SRB_STATUS_INVALID_REQUEST;
2713
2714 if (Srb->SenseInfoBuffer) {
2715
2716 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2717
2718 senseBuffer->ErrorCode = 0x70;
2719 senseBuffer->Valid = 1;
2720 senseBuffer->AdditionalSenseLength = 0xb;
2721 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
2722 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_VALUE;
2723 senseBuffer->AdditionalSenseCodeQualifier = SCSI_SENSEQ_PARAM_INVALID_VALUE;
2724 senseBuffer->IncorrectLength = 1;
2725
2726 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2727 }
2728
2729 } else if (errorByte & IDE_ERROR_BAD_BLOCK) {
2730
2731 KdPrint2((PRINT_PREFIX
2732 "IDE: Bad block\n"));
2733 srbStatus = SRB_STATUS_ERROR;
2734 scsiStatus = SCSISTAT_CHECK_CONDITION;
2735 if (Srb->SenseInfoBuffer) {
2736
2737 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2738
2739 senseBuffer->ErrorCode = 0x70;
2740 senseBuffer->Valid = 1;
2741 senseBuffer->AdditionalSenseLength = 0xb;
2742 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
2743 senseBuffer->AdditionalSenseCode = 0;
2744 senseBuffer->AdditionalSenseCodeQualifier = 0;
2745
2746 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2747 }
2748
2749 } else if (errorByte & IDE_ERROR_ID_NOT_FOUND) {
2750
2751 KdPrint2((PRINT_PREFIX
2752 "IDE: Id not found\n"));
2753 srbStatus = SRB_STATUS_ERROR;
2754 scsiStatus = SCSISTAT_CHECK_CONDITION;
2755
2756 if (Srb->SenseInfoBuffer) {
2757
2758 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2759
2760 senseBuffer->ErrorCode = 0x70;
2761 senseBuffer->Valid = 1;
2762 senseBuffer->AdditionalSenseLength = 0xb;
2763 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
2764 senseBuffer->AdditionalSenseCode = 0;
2765 senseBuffer->AdditionalSenseCodeQualifier = 0;
2766
2767 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2768 }
2769
2770 LunExt->ErrorCount++;
2771
2772 } else if (errorByte & IDE_ERROR_MEDIA_CHANGE) {
2773
2774 KdPrint2((PRINT_PREFIX
2775 "IDE: Media change\n"));
2776 scsiStatus = SCSISTAT_CHECK_CONDITION;
2777 srbStatus = SRB_STATUS_ERROR;
2778
2779 if (Srb->SenseInfoBuffer) {
2780
2781 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2782
2783 senseBuffer->ErrorCode = 0x70;
2784 senseBuffer->Valid = 1;
2785 senseBuffer->AdditionalSenseLength = 0xb;
2786 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
2787 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
2788 senseBuffer->AdditionalSenseCodeQualifier = 0;
2789
2790 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2791 }
2792
2793 } else if (errorByte & IDE_ERROR_DATA_ERROR) {
2794
2795 KdPrint2((PRINT_PREFIX
2796 "IDE: Data error\n"));
2797 scsiStatus = SCSISTAT_CHECK_CONDITION;
2798 srbStatus = SRB_STATUS_ERROR;
2799
2800 if (!(LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)){
2801 LunExt->ErrorCount++;
2802 }
2803
2804 // Build sense buffer
2805 if (Srb->SenseInfoBuffer) {
2806
2807 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
2808
2809 senseBuffer->ErrorCode = 0x70;
2810 senseBuffer->Valid = 1;
2811 senseBuffer->AdditionalSenseLength = 0xb;
2812 senseBuffer->SenseKey = SCSI_SENSE_MEDIUM_ERROR;
2813 senseBuffer->AdditionalSenseCode = 0;
2814 senseBuffer->AdditionalSenseCodeQualifier = 0;
2815
2816 srbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2817 }
2818 }
2819
2820 if (LunExt->ErrorCount >= MAX_ERRORS) {
2821 // deviceExtension->DWordIO = FALSE;
2822
2823 KdPrint2((PRINT_PREFIX
2824 "MapError: ErrorCount >= MAX_ERRORS\n"));
2825
2826 LunExt->DeviceFlags &= ~DFLAGS_DWORDIO_ENABLED;
2827 LunExt->MaximumBlockXfer = 0;
2828 BrutePoint();
2829
2830 KdPrint2((PRINT_PREFIX
2831 "MapError: Disabling 32-bit PIO and Multi-sector IOs\n"));
2832
2833 // Log the error.
2834 KdPrint2((PRINT_PREFIX
2835 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
2836 HwDeviceExtension,
2837 Srb,
2838 Srb->PathId,
2839 Srb->TargetId,
2840 Srb->Lun,
2841 SP_BAD_FW_WARNING,
2842 4
2843 ));
2844 ScsiPortLogError( HwDeviceExtension,
2845 Srb,
2846 Srb->PathId,
2847 Srb->TargetId,
2848 Srb->Lun,
2849 SP_BAD_FW_WARNING,
2850 4);
2851
2852 // Reprogram to not use Multi-sector.
2853 UCHAR statusByte;
2854
2855 if (LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT &&
2856 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
2857
2858 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_SET_MULTIPLE, 0, 0, 0, 0, 0, ATA_WAIT_BASE_READY);
2859
2860 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2861 // command was aborted.
2862 if (statusByte & IDE_STATUS_ERROR) {
2863
2864 // Read the error register.
2865 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2866
2867 KdPrint2((PRINT_PREFIX "MapError: Error setting multiple mode. Status %#x, error byte %#x\n",
2868 statusByte,
2869 errorByte));
2870
2871 // Adjust the devExt. value, if necessary.
2872 LunExt->MaximumBlockXfer = 0;
2873 BrutePoint();
2874
2875 }
2876 }
2877 }
2878 }
2879
2880 // Set SCSI status to indicate a check condition.
2881 Srb->ScsiStatus = scsiStatus;
2882
2883 return srbStatus;
2884
2885 } // end MapError()
2886
2887
2888 /*++
2889
2890 Routine Description:
2891
2892 Arguments:
2893 HwDeviceExtension - HBA miniport driver's adapter data storage
2894 ->HwInitialize
2895
2896 Return Value:
2897 TRUE - if initialization successful.
2898 FALSE - if initialization unsuccessful.
2899
2900 --*/
2901 BOOLEAN
2902 NTAPI
2903 AtapiHwInitialize(
2904 IN PVOID HwDeviceExtension
2905 )
2906 {
2907 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2908 ULONG numberChannels = deviceExtension->NumberChannels;
2909 ULONG c;
2910
2911 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base)\n"));
2912
2913 if(WinVer_WDM_Model) {
2914 AtapiResetController__(HwDeviceExtension, CHAN_NOT_SPECIFIED, RESET_COMPLETE_ALL);
2915 }
2916 if(deviceExtension->MasterDev) {
2917 KdPrint2((PRINT_PREFIX " mark chan %d of master controller [%x] as inited\n",
2918 deviceExtension->Channel, deviceExtension->DevIndex));
2919 BMList[deviceExtension->DevIndex].ChanInitOk |= 0x01 << deviceExtension->Channel;
2920 }
2921
2922 /* do extra chipset specific setups */
2923 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
2924 /*
2925 if(deviceExtension->Isr2DevObj && (deviceExtension->HwFlags & UNIATA_SATA)) {
2926 KdPrint2((PRINT_PREFIX " enable ISR2 to catch unexpected interrupts\n"));
2927 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
2928 }
2929 */
2930 for (c = 0; c < numberChannels; c++) {
2931 AtapiHwInitialize__(deviceExtension, c);
2932 }
2933 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: (base) done\n"));
2934 return TRUE;
2935 } // end AtapiHwInitialize()
2936
2937 VOID
2938 NTAPI
2939 AtapiHwInitialize__(
2940 IN PHW_DEVICE_EXTENSION deviceExtension,
2941 IN ULONG lChannel
2942 )
2943 {
2944 ULONG i;
2945 UCHAR statusByte, errorByte;
2946 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
2947 PHW_LU_EXTENSION LunExt;
2948 // ULONG tmp32;
2949 ULONG PreferedMode = 0xffffffff;
2950
2951 if((deviceExtension->HwFlags & UNIATA_AHCI) &&
2952 !UniataAhciChanImplemented(deviceExtension, lChannel)) {
2953 return;
2954 }
2955
2956 AtapiChipInit(deviceExtension, DEVNUM_NOT_SPECIFIED, lChannel);
2957 FindDevices(deviceExtension, 0, lChannel);
2958
2959 for (i = 0; i < chan->NumberLuns; i++) {
2960
2961 KdPrint3((PRINT_PREFIX "AtapiHwInitialize: lChannel %#x, dev %x\n", lChannel, i));
2962
2963 LunExt = chan->lun[i];
2964 // skip empty slots
2965 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
2966 continue;
2967 }
2968
2969 AtapiDisableInterrupts(deviceExtension, lChannel);
2970 AtapiStallExecution(1);
2971
2972 if (!(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_MANUAL_CHS))) {
2973
2974 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: IDE branch\n"));
2975 // Enable media status notification
2976 IdeMediaStatus(TRUE,deviceExtension,lChannel,(UCHAR)i);
2977
2978 // If supported, setup Multi-block transfers.
2979 statusByte = AtaCommand(deviceExtension, i, lChannel,
2980 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
2981 LunExt->MaximumBlockXfer, 0, ATA_WAIT_BASE_READY);
2982
2983 // Check for errors. Reset the value to 0 (disable MultiBlock) if the
2984 // command was aborted.
2985 if (statusByte & IDE_STATUS_ERROR) {
2986
2987 // Read the error register.
2988 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
2989
2990 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error setting multiple mode. Status %#x, error byte %#x\n",
2991 statusByte,
2992 errorByte));
2993
2994 statusByte = AtaCommand(deviceExtension, i, lChannel,
2995 IDE_COMMAND_SET_MULTIPLE, 0, 0, 0,
2996 0, 0, ATA_WAIT_BASE_READY);
2997
2998 if (statusByte & IDE_STATUS_ERROR) {
2999 // Read the error register.
3000 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
3001
3002 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: Error disabling multiple mode. Status %#x, error byte %#x\n",
3003 statusByte,
3004 errorByte));
3005 }
3006 // Adjust the devExt. value, if necessary.
3007 LunExt->MaximumBlockXfer = 0;
3008
3009 } else {
3010 KdPrint2((PRINT_PREFIX
3011 "AtapiHwInitialize: Using Multiblock on Device %d. Blocks / int - %d\n",
3012 i,
3013 LunExt->MaximumBlockXfer));
3014 }
3015
3016 if(LunExt->IdentifyData.MajorRevision) {
3017
3018 if(LunExt->opt_ReadCacheEnable) {
3019 KdPrint2((PRINT_PREFIX " Try Enable Read Cache\n"));
3020 // If supported, setup read/write cacheing
3021 statusByte = AtaCommand(deviceExtension, i, lChannel,
3022 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3023 0, ATA_C_F_ENAB_RCACHE, ATA_WAIT_BASE_READY);
3024
3025 // Check for errors.
3026 if (statusByte & IDE_STATUS_ERROR) {
3027 KdPrint2((PRINT_PREFIX
3028 "AtapiHwInitialize: Enable read/write cacheing on Device %d failed\n",
3029 i));
3030 LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
3031 } else {
3032 LunExt->DeviceFlags |= DFLAGS_RCACHE_ENABLED;
3033 }
3034 } else {
3035 KdPrint2((PRINT_PREFIX " Disable Read Cache\n"));
3036 statusByte = AtaCommand(deviceExtension, i, lChannel,
3037 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3038 0, ATA_C_F_DIS_RCACHE, ATA_WAIT_BASE_READY);
3039 LunExt->DeviceFlags &= ~DFLAGS_RCACHE_ENABLED;
3040 }
3041 if(LunExt->opt_WriteCacheEnable) {
3042 KdPrint2((PRINT_PREFIX " Try Enable Write Cache\n"));
3043 // If supported & allowed, setup write cacheing
3044 statusByte = AtaCommand(deviceExtension, i, lChannel,
3045 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3046 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
3047 // Check for errors.
3048 if (statusByte & IDE_STATUS_ERROR) {
3049 KdPrint2((PRINT_PREFIX
3050 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
3051 i));
3052 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
3053 } else {
3054 LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
3055 }
3056 } else {
3057 KdPrint2((PRINT_PREFIX " Disable Write Cache\n"));
3058 statusByte = AtaCommand(deviceExtension, i, lChannel,
3059 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3060 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
3061 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
3062 }
3063
3064 if(LunExt->IdentifyData.FeaturesSupport.PowerMngt ||
3065 LunExt->IdentifyData.FeaturesSupport.APM) {
3066
3067 if(LunExt->opt_AdvPowerMode) {
3068 KdPrint2((PRINT_PREFIX " Try Enable Adv. Power Mgmt\n"));
3069 // setup APM
3070 statusByte = AtaCommand(deviceExtension, i, lChannel,
3071 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3072 LunExt->opt_AdvPowerMode, ATA_C_F_ENAB_APM, ATA_WAIT_BASE_READY);
3073 // Check for errors.
3074 if (statusByte & IDE_STATUS_ERROR) {
3075 KdPrint2((PRINT_PREFIX
3076 "AtapiHwInitialize: Enable APM on Device %d failed\n",
3077 i));
3078 }
3079 } else {
3080 KdPrint2((PRINT_PREFIX " Disable Adv. Power Mgmt\n"));
3081 statusByte = AtaCommand(deviceExtension, i, lChannel,
3082 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3083 0, ATA_C_F_DIS_APM, ATA_WAIT_BASE_READY);
3084 }
3085 }
3086 if(LunExt->IdentifyData.FeaturesSupport.AutoAcoustic) {
3087 if(LunExt->opt_AcousticMode) {
3088 KdPrint2((PRINT_PREFIX " Try Enable Acoustic Mgmt\n"));
3089 // setup acoustic mgmt
3090 statusByte = AtaCommand(deviceExtension, i, lChannel,
3091 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3092 LunExt->opt_AcousticMode, ATA_C_F_ENAB_ACOUSTIC, ATA_WAIT_BASE_READY);
3093 // Check for errors.
3094 if (statusByte & IDE_STATUS_ERROR) {
3095 KdPrint2((PRINT_PREFIX
3096 "AtapiHwInitialize: Enable Acoustic Mgmt on Device %d failed\n",
3097 i));
3098 }
3099 } else {
3100 KdPrint2((PRINT_PREFIX " Disable Acoustic Mgmt\n"));
3101 statusByte = AtaCommand(deviceExtension, i, lChannel,
3102 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
3103 0, ATA_C_F_DIS_ACOUSTIC, ATA_WAIT_BASE_READY);
3104 }
3105 }
3106 if(LunExt->IdentifyData.FeaturesSupport.Standby) {
3107 KdPrint2((PRINT_PREFIX " Try init standby timer: %d\n"));
3108 // setup standby timer
3109 statusByte = AtaCommand(deviceExtension, i, lChannel,
3110 IDE_COMMAND_IDLE, 0, 0, 0,
3111 LunExt->opt_StandbyTimer, 0, ATA_WAIT_BASE_READY);
3112 // Check for errors.
3113 if (statusByte & IDE_STATUS_ERROR) {
3114 KdPrint2((PRINT_PREFIX
3115 "AtapiHwInitialize: standby timer on Device %d failed\n",
3116 i));
3117 }
3118 }
3119 }
3120
3121 } else if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)){
3122
3123 ULONG j;
3124 BOOLEAN isSanyo = FALSE;
3125 CCHAR vendorId[26];
3126
3127 KdPrint2((PRINT_PREFIX "AtapiHwInitialize: ATAPI/Changer branch\n"));
3128
3129 // Attempt to identify any special-case devices - psuedo-atapi changers, atapi changers, etc.
3130 for (j = 0; j < 26; j += 2) {
3131
3132 // Build a buffer based on the identify data.
3133 MOV_DW_SWP(vendorId[j], ((PUCHAR)LunExt->IdentifyData.ModelNumber)[j]);
3134 }
3135
3136 if (!AtapiStringCmp (vendorId, "CD-ROM CDR", 11)) {
3137
3138 // Inquiry string for older model had a '-', newer is '_'
3139 if (vendorId[12] == 'C') {
3140
3141 // Torisan changer. Set the bit. This will be used in several places
3142 // acting like 1) a multi-lun device and 2) building the 'special' TUR's.
3143 LunExt->DeviceFlags |= (DFLAGS_CHANGER_INITED | DFLAGS_SANYO_ATAPI_CHANGER);
3144 LunExt->DiscsPresent = 3;
3145 isSanyo = TRUE;
3146 }
3147 }
3148 }
3149
3150 PreferedMode = LunExt->opt_MaxTransferMode;
3151 if((PreferedMode == 0xffffffff) || (PreferedMode > chan->MaxTransferMode)) {
3152 KdPrint2((PRINT_PREFIX "MaxTransferMode (overriden): %#x\n", chan->MaxTransferMode));
3153 PreferedMode = chan->MaxTransferMode;
3154 }
3155
3156 if(LunExt->opt_PreferedTransferMode != 0xffffffff) {
3157 KdPrint2((PRINT_PREFIX "PreferedTransferMode: %#x\n", PreferedMode));
3158 PreferedMode = min(LunExt->opt_PreferedTransferMode, PreferedMode);
3159 }
3160
3161 KdPrint2((PRINT_PREFIX " try mode %#x\n", PreferedMode));
3162 LunExt->LimitedTransferMode =
3163 LunExt->TransferMode =
3164 (CHAR)PreferedMode;
3165
3166 AtapiDmaInit__(deviceExtension, LunExt);
3167
3168 LunExt->LimitedTransferMode =
3169 LunExt->TransferMode;
3170 KdPrint2((PRINT_PREFIX "Using %#x mode\n", LunExt->TransferMode));
3171
3172 // We need to get our device ready for action before
3173 // returning from this function
3174
3175 // According to the atapi spec 2.5 or 2.6, an atapi device
3176 // clears its status BSY bit when it is ready for atapi commands.
3177 // However, some devices (Panasonic SQ-TC500N) are still
3178 // not ready even when the status BSY is clear. They don't react
3179 // to atapi commands.
3180 //
3181 // Since there is really no other indication that tells us
3182 // the drive is really ready for action. We are going to check BSY
3183 // is clear and then just wait for an arbitrary amount of time!
3184 //
3185 if (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
3186 ULONG waitCount;
3187
3188 // have to get out of the loop sometime!
3189 // 10000 * 100us = 1000,000us = 1000ms = 1s
3190 waitCount = 10000;
3191 GetStatus(chan, statusByte);
3192 if(statusByte == IDE_STATUS_WRONG) {
3193 waitCount = 0;
3194 }
3195 while ((statusByte & IDE_STATUS_BUSY) && waitCount) {
3196
3197 KdPrint2((PRINT_PREFIX "Wait for ATAPI (status %x)\n", statusByte));
3198 // Wait for Busy to drop.
3199 AtapiStallExecution(100);
3200 GetStatus(chan, statusByte);
3201 waitCount--;
3202 }
3203
3204 // 5000 * 100us = 500,000us = 500ms = 0.5s
3205 if(statusByte != IDE_STATUS_WRONG) {
3206 waitCount = 5000;
3207 do {
3208 AtapiStallExecution(100);
3209 } while (waitCount--);
3210 }
3211 }
3212 GetBaseStatus(chan, statusByte);
3213 AtapiEnableInterrupts(deviceExtension, lChannel);
3214 AtapiStallExecution(10);
3215 }
3216
3217 return;
3218
3219 } // end AtapiHwInitialize__()
3220
3221
3222 #ifndef UNIATA_CORE
3223
3224 VOID
3225 NTAPI
3226 AtapiHwInitializeChanger(
3227 IN PVOID HwDeviceExtension,
3228 IN PSCSI_REQUEST_BLOCK Srb,
3229 IN PMECHANICAL_STATUS_INFORMATION_HEADER MechanismStatus)
3230 {
3231 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3232 ULONG lChannel = GET_CHANNEL(Srb);
3233 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3234 ULONG DeviceNumber = GET_CDEV(Srb);
3235 PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
3236
3237 if (MechanismStatus) {
3238 LunExt->DiscsPresent = MechanismStatus->NumberAvailableSlots;
3239 if (LunExt->DiscsPresent > 1) {
3240 LunExt->DeviceFlags |= DFLAGS_ATAPI_CHANGER;
3241 }
3242 }
3243 return;
3244 } // end AtapiHwInitializeChanger()
3245
3246
3247 /*++
3248
3249 Routine Description:
3250 This routine will parse the string for a match on the keyword, then
3251 calculate the value for the keyword and return it to the caller.
3252
3253 Arguments:
3254 String - The ASCII string to parse.
3255 KeyWord - The keyword for the value desired.
3256
3257 Return Values:
3258 Zero if value not found
3259 Value converted from ASCII to binary.
3260
3261 --*/
3262 ULONG
3263 NTAPI
3264 AtapiParseArgumentString(
3265 IN PCCH String,
3266 IN PCCH KeyWord
3267 )
3268 {
3269 PCCH cptr;
3270 PCCH kptr;
3271 ULONG value;
3272 ULONG stringLength = 0;
3273 ULONG keyWordLength = 0;
3274 ULONG index;
3275
3276 if (!String) {
3277 return 0;
3278 }
3279 if (!KeyWord) {
3280 return 0;
3281 }
3282
3283 // Calculate the string length and lower case all characters.
3284 cptr = String;
3285 while (*cptr++) {
3286 stringLength++;
3287 }
3288
3289 // Calculate the keyword length.
3290 kptr = KeyWord;
3291 while (*kptr++) {
3292 keyWordLength++;
3293 }
3294
3295 if (keyWordLength > stringLength) {
3296
3297 // Can't possibly have a match.
3298 return 0;
3299 }
3300
3301 // Now setup and start the compare.
3302 cptr = String;
3303
3304 ContinueSearch:
3305
3306 // The input string may start with white space. Skip it.
3307 while (*cptr == ' ' || *cptr == '\t') {
3308 cptr++;
3309 }
3310
3311 if (*cptr == '\0') {
3312 // end of string.
3313 return 0;
3314 }
3315
3316 kptr = KeyWord;
3317 while ((*cptr == *kptr) ||
3318 (*cptr >= 'A' && *cptr <= 'Z' && *cptr + ('a' - 'A') == *kptr) ||
3319 (*cptr >= 'a' && *cptr <= 'z' && *cptr - ('a' - 'A') == *kptr)) {
3320 cptr++;
3321 kptr++;
3322
3323 if (*cptr == '\0') {
3324 // end of string
3325 return 0;
3326 }
3327 }
3328
3329 if (*kptr == '\0') {
3330
3331 // May have a match backup and check for blank or equals.
3332 while (*cptr == ' ' || *cptr == '\t') {
3333 cptr++;
3334 }
3335
3336 // Found a match. Make sure there is an equals.
3337 if (*cptr != '=') {
3338
3339 // Not a match so move to the next semicolon.
3340 while (*cptr) {
3341 if (*cptr++ == ';') {
3342 goto ContinueSearch;
3343 }
3344 }
3345 return 0;
3346 }
3347 // Skip the equals sign.
3348 cptr++;
3349
3350 // Skip white space.
3351 while ((*cptr == ' ') || (*cptr == '\t')) {
3352 cptr++;
3353 }
3354
3355 if (*cptr == '\0') {
3356 // Early end of string, return not found
3357 return 0;
3358 }
3359
3360 if (*cptr == ';') {
3361 // This isn't it either.
3362 cptr++;
3363 goto ContinueSearch;
3364 }
3365
3366 value = 0;
3367 if ((*cptr == '0') && ((*(cptr + 1) == 'x') || (*(cptr + 1) == 'X'))) {
3368 // Value is in Hex. Skip the "0x"
3369 cptr += 2;
3370 for (index = 0; *(cptr + index); index++) {
3371
3372 if (*(cptr + index) == ' ' ||
3373 *(cptr + index) == '\t' ||
3374 *(cptr + index) == ';') {
3375 break;
3376 }
3377
3378 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3379 value = (16 * value) + (*(cptr + index) - '0');
3380 } else {
3381 if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) {
3382 value = (16 * value) + (*(cptr + index) - 'a' + 10);
3383 } else if ((*(cptr + index) >= 'A') && (*(cptr + index) <= 'F')) {
3384 value = (16 * value) + (*(cptr + index) - 'A' + 10);
3385 } else {
3386 // Syntax error, return not found.
3387 return 0;
3388 }
3389 }
3390 }
3391 } else {
3392
3393 // Value is in Decimal.
3394 for (index = 0; *(cptr + index); index++) {
3395
3396 if (*(cptr + index) == ' ' ||
3397 *(cptr + index) == '\t' ||
3398 *(cptr + index) == ';') {
3399 break;
3400 }
3401
3402 if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) {
3403 value = (10 * value) + (*(cptr + index) - '0');
3404 } else {
3405
3406 // Syntax error return not found.
3407 return 0;
3408 }
3409 }
3410 }
3411
3412 return value;
3413 } else {
3414
3415 // Not a match check for ';' to continue search.
3416 while (*cptr) {
3417 if (*cptr++ == ';') {
3418 goto ContinueSearch;
3419 }
3420 }
3421
3422 return 0;
3423 }
3424 } // end AtapiParseArgumentString()_
3425
3426 /*
3427 Timer callback
3428 */
3429 VOID
3430 NTAPI
3431 AtapiCallBack__(
3432 IN PVOID HwDeviceExtension,
3433 IN UCHAR lChannel
3434 )
3435 {
3436
3437 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3438 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
3439 ULONG c, _c;
3440
3441 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
3442 UCHAR statusByte;
3443
3444 KdPrint2((PRINT_PREFIX "AtapiCallBack:\n"));
3445 // If the last command was DSC restrictive, see if it's set. If so, the device is
3446 // ready for a new request. Otherwise, reset the timer and come back to here later.
3447
3448 // If ISR decided to wait for BUSY or DRQ in DPC, we shall also get here.
3449 // In this case chan->ExpectingInterrupt == TRUE, but interrupts are disabled, thus,
3450 // we shall have no problem with interrupt handler.
3451 if (!srb || chan->ExpectingInterrupt) {
3452 KdPrint2((PRINT_PREFIX "AtapiCallBack: Calling ISR directly due to BUSY\n"));
3453 chan->DpcState = DPC_STATE_TIMER;
3454 if(!AtapiInterrupt__(HwDeviceExtension, lChannel)) {
3455 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
3456 KdPrint2((PRINT_PREFIX "AtapiCallBack: What's fucking this ???\n"));
3457 }
3458 goto ReturnCallback;
3459 }
3460
3461 #ifdef DBG
3462 if (!IS_RDP((srb->Cdb[0]))) {
3463 KdPrint2((PRINT_PREFIX "AtapiCallBack: Invalid CDB marked as RDP - %#x\n", srb->Cdb[0]));
3464 }
3465 #endif
3466 if(!(chan->RDP)) {
3467 goto ReturnEnableIntr;
3468 }
3469 GetStatus(chan, statusByte);
3470 if (statusByte & IDE_STATUS_DSC) {
3471
3472 UCHAR PathId = srb->PathId;
3473 UCHAR TargetId = srb->TargetId;
3474 UCHAR Lun = srb->Lun;
3475
3476 KdPrint2((PRINT_PREFIX "AtapiCallBack: Found DSC for RDP - %#x\n", srb->Cdb[0]));
3477 AtapiDmaDBSync(chan, srb);
3478 UniataRemoveRequest(chan, srb);
3479 ScsiPortNotification(RequestComplete, deviceExtension, srb);
3480 // Clear current SRB.
3481 if(!deviceExtension->simplexOnly) {
3482 srb = UniataGetCurRequest(chan);
3483 } else {
3484 srb = NULL;
3485 }
3486 chan->RDP = FALSE;
3487
3488 // Ask for next request.
3489 ScsiPortNotification(NextLuRequest,
3490 deviceExtension,
3491 PathId,
3492 TargetId,
3493 Lun);
3494 ScsiPortNotification(NextRequest, deviceExtension, NULL);
3495
3496 if(srb) {
3497 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
3498 }
3499
3500 } else {
3501 KdPrint2((PRINT_PREFIX "AtapiCallBack: Requesting another timer for Op %#x\n",
3502 srb->Cdb[0]));
3503
3504 AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3505 AtapiCallBack_X,
3506 1000);
3507
3508 goto ReturnCallback;
3509 }
3510
3511 ReturnEnableIntr:
3512
3513 if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
3514 KdPrint2((PRINT_PREFIX "AtapiCallBack: CallDisableInterrupts\n"));
3515 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
3516 #ifdef UNIATA_USE_XXableInterrupts
3517 chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
3518 // must be called on DISPATCH_LEVEL
3519 ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
3520 AtapiEnableInterrupts__);
3521 #else
3522 AtapiEnableInterrupts(HwDeviceExtension, lChannel);
3523 InterlockedExchange(&(chan->CheckIntr),
3524 CHECK_INTR_IDLE);
3525 // Will raise IRQL to DIRQL
3526 AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
3527 AtapiEnableInterrupts__,
3528 1);
3529 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
3530 #endif // UNIATA_USE_XXableInterrupts
3531 } else {
3532 //ASSERT(!deviceExtension->simplexOnly);
3533 }
3534
3535 ReturnCallback:
3536
3537 // Check other channel
3538 // In simplex mode no interrupts must appear on other channels
3539 for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3540 c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
3541
3542 if(c == lChannel) {
3543 continue;
3544 }
3545
3546 chan = &(deviceExtension->chan[c]);
3547
3548 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
3549 CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
3550 CRNT_ILK_TYPE CHECK_INTR_DETECTED) == CHECK_INTR_DETECTED)
3551 {
3552 //ASSERT(!deviceExtension->simplexOnly);
3553 chan->DpcState = DPC_STATE_ISR;
3554 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3555 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
3556 }
3557 }
3558 }
3559 KdPrint2((PRINT_PREFIX "AtapiCallBack: return\n"));
3560 return;
3561
3562 } // end AtapiCallBack__()
3563
3564 VOID
3565 NTAPI
3566 AtapiCallBack_X(
3567 IN PVOID HwDeviceExtension
3568 )
3569 {
3570 AtapiCallBack__(HwDeviceExtension, (UCHAR)((PHW_DEVICE_EXTENSION)HwDeviceExtension)->ActiveDpcChan);
3571 } // end AtapiCallBack_X()
3572
3573 #endif //UNIATA_CORE
3574
3575 /*++
3576
3577 Routine Description:
3578
3579 This is the interrupt service routine for ATAPI IDE miniport driver.
3580
3581 Arguments:
3582
3583 HwDeviceExtension - HBA miniport driver's adapter data storage
3584
3585 Return Value:
3586
3587 TRUE if expecting an interrupt.
3588
3589 --*/
3590 BOOLEAN
3591 NTAPI
3592 AtapiInterrupt(
3593 IN PVOID HwDeviceExtension
3594 )
3595 {
3596 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3597 ULONG c, _c;
3598 BOOLEAN status = FALSE;
3599 ULONG c_state;
3600 ULONG i_res = 0;
3601 ULONG pass;
3602 //BOOLEAN checked[AHCI_MAX_PORT];
3603 ULONG hIS;
3604 ULONG checked;
3605
3606 KdPrint2((PRINT_PREFIX "Intr: VendorID+DeviceID/Rev %#x/%#x (ex %d)\n",
3607 deviceExtension->DevID, deviceExtension->RevID, deviceExtension->ExpectingInterrupt ));
3608
3609 if(deviceExtension->HwFlags & UNIATA_AHCI) {
3610 // AHCI may generate state change notification, never skip this check
3611 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
3612 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
3613 if(!hIS) {
3614 return FALSE;
3615 }
3616 // assume all non-interrupted ports to be already checked
3617 checked = ~hIS;
3618 // assume all not implemented ports to be already checked
3619 checked |= ~deviceExtension->AHCI_PI;
3620 } else {
3621 checked = 0; // assume all ports are not checked
3622 }
3623
3624 if(!deviceExtension->ExpectingInterrupt) {
3625 // if we do not expect interrupt, exit now,
3626 // but keep in mind that it can be unexpected one
3627 // Note: this is just a hint, not exact counter
3628 KdPrint2((PRINT_PREFIX "unexpected, 1st chance\n"));
3629 //deviceExtension->ExpectingInterrupt++;
3630 //return FALSE;
3631 }
3632 // clear this flag now, it can be set again in sub-calls
3633 deviceExtension->ExpectingInterrupt=0;
3634
3635
3636 // for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3637 // checked[_c] = (UCHAR)((hIS >> _c) & 0x01);
3638 // }
3639
3640 // fc =
3641 for(pass=0; pass<2; pass++) {
3642 //KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): pass %d\n", pass));
3643 if(status && pass) {
3644 // we catched some expected interrupts now.
3645 // do not touch unexpected until next ISR call
3646 break;
3647 }
3648 for(_c=0; _c<deviceExtension->NumberChannels; _c++) {
3649
3650 c = (_c+deviceExtension->FirstChannelToCheck) % deviceExtension->NumberChannels;
3651
3652 if((checked>>c) & 0x01)
3653 continue;
3654
3655 // check non-empty and expecting interrupt channels first
3656 if(!pass && !deviceExtension->chan[c].ExpectingInterrupt)
3657 continue;
3658
3659 checked |= (ULONG)1 << c;
3660
3661 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
3662
3663 if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
3664 // we get here on idle channels or when ISR is posted to DPC
3665 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): disabled INTR on ch %d\n", c));
3666 continue;
3667 }
3668 // lock channel. Wait, while 2nd ISR checks interrupt on this channel
3669 do {
3670 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): try lock\n"));
3671 // c_state = deviceExtension->chan[c].CheckIntr;
3672 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_DETECTED) {
3673 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE;
3674 // }
3675 c_state =
3676 (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
3677 CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
3678 CRNT_ILK_TYPE CHECK_INTR_DETECTED);
3679 if(c_state == CHECK_INTR_IDLE) {
3680 // c_state = deviceExtension->chan[c].CheckIntr;
3681 // if (deviceExtension->chan[c].CheckIntr == CHECK_INTR_IDLE) {
3682 // deviceExtension->chan[c].CheckIntr = CHECK_INTR_ACTIVE
3683 // }
3684 c_state =
3685 (ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
3686 CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
3687 CRNT_ILK_TYPE CHECK_INTR_IDLE);
3688 }
3689 } while(c_state == CHECK_INTR_CHECK);
3690 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): locked\n"));
3691 // check if already serviced
3692 if(c_state == CHECK_INTR_ACTIVE) {
3693 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): CHECK_INTR_ACTIVE\n"));
3694 continue;
3695 }
3696
3697 if((c_state == CHECK_INTR_DETECTED) ||
3698 (i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
3699
3700 if(i_res == INTERRUPT_REASON_UNEXPECTED) {
3701 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): Catch unexpected\n"));
3702 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3703 //return TRUE;
3704 status = TRUE;
3705 continue;
3706 }
3707 // disable interrupts on other channel of legacy mode
3708 // ISA-bridged onboard controller
3709 if(deviceExtension->simplexOnly /*||
3710 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3711 AtapiDisableInterrupts(deviceExtension, !c);
3712 }
3713
3714 deviceExtension->chan[c].DpcState = DPC_STATE_ISR;
3715 if(AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3716 deviceExtension->LastInterruptedChannel = (UCHAR)c;
3717 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): return status TRUE\n"));
3718 status = TRUE;
3719 } else {
3720 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE\n"));
3721 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3722 }
3723
3724 // re-enable interrupts on other channel
3725 if(deviceExtension->simplexOnly /*||
3726 ((WinVer_Id() > WinVer_NT) && BMList[deviceExtension->DevIndex].MasterDev)*/) {
3727 AtapiEnableInterrupts(deviceExtension, !c);
3728 }
3729
3730 } else {
3731 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): set CHECK_INTR_IDLE (2)\n"));
3732 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3733 }
3734
3735 }
3736 }
3737 KdPrint2((PRINT_PREFIX "AtapiInterrupt(base): exit with status %#x\n", status));
3738 if(status) {
3739 deviceExtension->FirstChannelToCheck++;
3740 if(deviceExtension->FirstChannelToCheck >= deviceExtension->NumberChannels)
3741 deviceExtension->FirstChannelToCheck = 0;
3742 }
3743 return status;
3744 } // end AtapiInterrupt()
3745
3746 //ULONG i2c = 0;
3747 #ifndef UNIATA_CORE
3748
3749 BOOLEAN
3750 NTAPI
3751 AtapiInterrupt2(
3752 IN PKINTERRUPT Interrupt,
3753 IN PVOID Isr2HwDeviceExtension
3754 )
3755 {
3756 // This ISR is intended to catch interrupts when we are already in other ISR instance
3757 // for the same device. This may happen when we have multiple channels,
3758 // especially on SMP machines
3759
3760 PISR2_DEVICE_EXTENSION Isr2DeviceExtension = (PISR2_DEVICE_EXTENSION)Isr2HwDeviceExtension;
3761 PHW_DEVICE_EXTENSION deviceExtension = Isr2DeviceExtension->HwDeviceExtension;
3762 ULONG c;
3763 BOOLEAN status = FALSE;
3764 ULONG c_count = 0;
3765 ULONG i_res;
3766 ULONG hIS;
3767 ULONG checked;
3768
3769 // we should never get here for ISA/MCA
3770 if(!BMList[deviceExtension->DevIndex].Isr2Enable) {
3771 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: NOT ACTIVE cntrlr %#x chan %#x\n",deviceExtension->DevIndex, deviceExtension->Channel));
3772 return FALSE;
3773 }
3774
3775 if(deviceExtension->HwFlags & UNIATA_AHCI) {
3776 // AHCI may generate state change notification, never skip this check
3777 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS);
3778 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: AHCI: hIS=%x cntrlr %#x chan %#x\n",hIS, deviceExtension->DevIndex, deviceExtension->Channel));
3779 if(!hIS) {
3780 return FALSE;
3781 }
3782 // assume all non-interrupted ports to be already checked
3783 checked = ~hIS;
3784 // assume all not implemented ports to be already checked
3785 checked |= ~deviceExtension->AHCI_PI;
3786
3787 } else {
3788 checked = 0; // assume all ports are not checked
3789 }
3790 if(!deviceExtension->ExpectingInterrupt) {
3791 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !deviceExtension->ExpectingInterrupt\n"));
3792 deviceExtension->ExpectingInterrupt++;
3793 return FALSE;
3794 }
3795 //deviceExtension->ExpectingInterrupt = 0;
3796
3797 for(c=0; c<deviceExtension->NumberChannels; c++) {
3798 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: cntrlr %#x chan %#x\n",deviceExtension->DevIndex, c));
3799
3800 if((checked>>c) & 0x01)
3801 continue;
3802
3803 checked |= (ULONG)1 << c;
3804
3805 if(CrNtInterlockedExchangeAdd(&(deviceExtension->chan[c].DisableIntr), 0)) {
3806 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: disabled INTR\n"));
3807 continue;
3808 }
3809
3810 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
3811 CRNT_ILK_TYPE CHECK_INTR_CHECK,
3812 CRNT_ILK_TYPE CHECK_INTR_IDLE) != CHECK_INTR_IDLE)
3813 {
3814 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: !CHECK_INTR_IDLE\n"));
3815 // hunt on unexpected intr (Some devices generate double interrupts,
3816 // some controllers (at least CMD649) interrupt twice with small delay.
3817 // If interrupts are disabled, they queue interrupt and re-issue it later,
3818 // when we do not expect it.
3819 continue;
3820 }
3821
3822 c_count++;
3823 if((i_res = AtapiCheckInterrupt__(deviceExtension, (UCHAR)c))) {
3824
3825 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: intr\n"));
3826 if(i_res == INTERRUPT_REASON_UNEXPECTED) {
3827 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: Catch unexpected\n"));
3828 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3829 return TRUE;
3830 }
3831
3832 status = TRUE;
3833 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_DETECTED);
3834 } else {
3835 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3836 }
3837 }
3838 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: status %d, c_count %d\n", status, c_count));
3839 if(status && (c_count != deviceExtension->NumberChannels)) {
3840 // there is an active ISR/DPC for one channel, but
3841 // we have an interrupt from another one
3842 // Lets inform current ISR/DPC about new interrupt
3843 InterlockedExchange(&(deviceExtension->ReCheckIntr), CHECK_INTR_DETECTED);
3844 } else {
3845 status = FALSE;
3846 }
3847 KdPrint2((PRINT_PREFIX "AtapiInterrupt2: return %d\n", status));
3848 return status;
3849
3850 } // end AtapiInterrupt2()
3851
3852 RETTYPE_XXableInterrupts
3853 NTAPI
3854 AtapiInterruptDpc(
3855 IN PVOID HwDeviceExtension
3856 )
3857 {
3858 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3859 ULONG c;
3860
3861 for(c=0; c<deviceExtension->NumberChannels; c++) {
3862 KdPrint2((PRINT_PREFIX "AtapiInterruptDpc: %#x\n",c));
3863
3864 if(!(deviceExtension->chan[c].ChannelCtrlFlags & CTRFLAGS_DPC_REQ)) {
3865
3866 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(deviceExtension->chan[c].CheckIntr),
3867 CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
3868 CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED)
3869 {
3870 continue;
3871 }
3872
3873 } else {
3874 deviceExtension->chan[c].ChannelCtrlFlags &= ~CTRFLAGS_DPC_REQ;
3875 }
3876 /*
3877 if(OldReqState != REQ_STATE_DPC_INTR_REQ) {
3878 AtapiDisableInterrupts(deviceExtension, lChannel);
3879 }
3880 */
3881 deviceExtension->chan[c].DpcState = DPC_STATE_DPC;
3882 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3883 InterlockedExchange(&(deviceExtension->chan[c].CheckIntr), CHECK_INTR_IDLE);
3884 }
3885 }
3886 return RETVAL_XXableInterrupts;
3887 } // end AtapiInterruptDpc()
3888
3889
3890 RETTYPE_XXableInterrupts
3891 NTAPI
3892 AtapiEnableInterrupts__(
3893 IN PVOID HwDeviceExtension
3894 )
3895 {
3896 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3897 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__():\n"));
3898 ULONG c;
3899 PHW_CHANNEL chan = NULL;
3900
3901 for(c=0; c<deviceExtension->NumberChannels; c++) {
3902 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts__(2): %#x\n",c));
3903 chan = &(deviceExtension->chan[c]);
3904
3905 if(chan->ChannelCtrlFlags & CTRFLAGS_ENABLE_INTR_REQ) {
3906 // enable intrs on requested channel
3907 chan->ChannelCtrlFlags &= ~CTRFLAGS_ENABLE_INTR_REQ;
3908 AtapiEnableInterrupts(HwDeviceExtension, c);
3909 InterlockedExchange(&(chan->CheckIntr),
3910 CHECK_INTR_IDLE);
3911
3912 // check if current or other channel(s) interrupted
3913 //AtapiInterrupt(HwDeviceExtension);
3914
3915 if(deviceExtension->simplexOnly) {
3916 break;
3917 }
3918 } else {
3919 // check if other channel(s) interrupted
3920 // must do nothing in simplex mode
3921 if((ULONG)CrNtInterlockedCompareExchange(CRNT_ILK_PTYPE &(chan->CheckIntr),
3922 CRNT_ILK_TYPE CHECK_INTR_ACTIVE,
3923 CRNT_ILK_TYPE CHECK_INTR_DETECTED) != CHECK_INTR_DETECTED) {
3924 continue;
3925 }
3926 //ASSERT(!deviceExtension->simplexOnly);
3927 chan->DpcState = DPC_STATE_ISR;
3928 if(!AtapiInterrupt__(HwDeviceExtension, (UCHAR)c)) {
3929 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
3930 }
3931 }
3932 }
3933 // In simplex mode next command must be sent to device here
3934 if(deviceExtension->simplexOnly && chan) {
3935 PSCSI_REQUEST_BLOCK srb;
3936 chan = UniataGetNextChannel(chan);
3937 if(chan) {
3938 srb = UniataGetCurRequest(chan);
3939 } else {
3940 srb = NULL;
3941 }
3942 if(srb) {
3943 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
3944 }
3945 }
3946
3947 return RETVAL_XXableInterrupts;
3948
3949 } // end AtapiEnableInterrupts__()
3950
3951 #endif //UNIATA_CORE
3952
3953
3954 VOID
3955 NTAPI
3956 AtapiEnableInterrupts(
3957 IN PVOID HwDeviceExtension,
3958 IN ULONG c
3959 )
3960 {
3961 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3962 PHW_CHANNEL chan;
3963 //UCHAR statusByte;
3964
3965 if(c >= deviceExtension->NumberChannels) {
3966 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: WRONG CHANNEL\n",c));
3967 return;
3968 }
3969 if((deviceExtension->HwFlags & UNIATA_AHCI) &&
3970 !UniataAhciChanImplemented(deviceExtension, c)) {
3971 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: not imp. CHANNEL\n",c));
3972 return;
3973 }
3974
3975 chan = &(deviceExtension->chan[c]);
3976 KdPrint2((PRINT_PREFIX "AtapiEnableInterrupts_%d: %d\n",c, chan->DisableIntr));
3977 if(!InterlockedDecrement(&chan->DisableIntr)) {
3978 if(deviceExtension->HwFlags & UNIATA_AHCI) {
3979 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE,
3980 (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
3981 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF |
3982 ((/*ch->pm_level == */0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
3983 ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC | /* DEBUG */
3984 ATA_AHCI_P_IX_DI |
3985 ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
3986 ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR)
3987 );
3988 } else {
3989 //SelectDrive(chan, 0);
3990 //GetBaseStatus(chan, statusByte);
3991 AtapiWritePort1(chan, IDX_IO2_o_Control,
3992 IDE_DC_A_4BIT );
3993 //if(chan->NumberLuns) {
3994 // SelectDrive(chan, 1);
3995 // GetBaseStatus(chan, statusByte);
3996 // AtapiWritePort1(chan, IDX_IO2_o_Control,
3997 // IDE_DC_A_4BIT );
3998 // SelectDrive(chan, chan->cur_cdev);
3999 //}
4000 }
4001 chan->ChannelCtrlFlags &= ~CTRFLAGS_INTR_DISABLED;
4002 } else {
4003 AtapiWritePort1(chan, IDX_IO2_o_Control,
4004 IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4005 }
4006 return;
4007 } // end AtapiEnableInterrupts()
4008
4009 VOID
4010 NTAPI
4011 AtapiDisableInterrupts(
4012 IN PVOID HwDeviceExtension,
4013 IN ULONG c
4014 )
4015 {
4016 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4017 PHW_CHANNEL chan;
4018 if(c >= deviceExtension->NumberChannels) {
4019 KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: WRONG CHANNEL\n",c));
4020 return;
4021 }
4022 chan = &(deviceExtension->chan[c]);
4023 KdPrint2((PRINT_PREFIX "AtapiDisableInterrupts_%d: %d\n",c, chan->DisableIntr));
4024 // mark channel as busy
4025 if(InterlockedIncrement(&chan->DisableIntr)) {
4026 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4027 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0);
4028 } else {
4029 //SelectDrive(chan, 0);
4030 AtapiWritePort1(chan, IDX_IO2_o_Control,
4031 IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4032 //if(chan->NumberLuns) {
4033 // SelectDrive(chan, 1);
4034 // AtapiWritePort1(chan, IDX_IO2_o_Control,
4035 // IDE_DC_DISABLE_INTERRUPTS /*| IDE_DC_A_4BIT*/ );
4036 // SelectDrive(chan, chan->cur_cdev);
4037 //}
4038 }
4039 chan->ChannelCtrlFlags |= CTRFLAGS_INTR_DISABLED;
4040 }
4041
4042 return;
4043 } // end AtapiDisableInterrupts()
4044
4045 VOID
4046 UniataExpectChannelInterrupt(
4047 IN struct _HW_CHANNEL* chan,
4048 IN BOOLEAN Expecting
4049 )
4050 {
4051 chan->ExpectingInterrupt = Expecting;
4052 if(Expecting) {
4053 chan->DeviceExtension->ExpectingInterrupt++;
4054 } else
4055 if(chan->DeviceExtension->ExpectingInterrupt) {
4056 chan->DeviceExtension->ExpectingInterrupt--;
4057 }
4058 return;
4059 } // end UniataExpectChannelInterrupt()
4060
4061 /*
4062 Check hardware for interrupt state
4063 */
4064 BOOLEAN
4065 NTAPI
4066 AtapiCheckInterrupt__(
4067 IN PVOID HwDeviceExtension,
4068 IN UCHAR c // logical channel
4069 )
4070 {
4071 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4072 PHW_CHANNEL chan = &(deviceExtension->chan[c]);
4073 PHW_LU_EXTENSION LunExt;
4074
4075 ULONG VendorID = deviceExtension->DevID & 0xffff;
4076 ULONG ChipType = deviceExtension->HwFlags & CHIPTYPE_MASK;
4077
4078 ULONG status;
4079 ULONG pr_status = 0;
4080 UCHAR dma_status = 0;
4081 UCHAR reg8 = 0;
4082 ULONG reg32 = 0;
4083 UCHAR statusByte = 0;
4084 ULONG slotNumber = deviceExtension->slotNumber;
4085 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
4086 ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
4087 UCHAR Channel;
4088 UCHAR lChannel;
4089 BOOLEAN DmaTransfer = FALSE;
4090 BOOLEAN OurInterrupt = FALSE;
4091 BOOLEAN StatusValid = FALSE;
4092 // ULONG k;
4093 UCHAR interruptReason;
4094 BOOLEAN EarlyIntr = FALSE;
4095 BOOLEAN SingleBlockIntr = FALSE;
4096
4097 KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n"));
4098
4099 lChannel = c;
4100 Channel = (UCHAR)(deviceExtension->Channel + lChannel);
4101 LunExt = chan->lun[chan->cur_cdev];
4102
4103 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ chan %#x:\n", chan));
4104 //KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__ (%d/%d):\n", Channel, chan->cur_cdev));
4105
4106 if((ChipFlags & UNIATA_AHCI) &&
4107 UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4108
4109 if(!UniataAhciChanImplemented(deviceExtension, lChannel)) {
4110 return OurInterrupt;
4111 }
4112
4113 OurInterrupt = UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
4114 if((OurInterrupt == INTERRUPT_REASON_UNEXPECTED) &&
4115 (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE)) {
4116 UniataAhciWaitCommandReady(chan, 2 /* ms */ );
4117 statusByte = (UCHAR)UniataAhciWaitReady(chan, 0 /* immediate */);
4118 if(!(statusByte & (IDE_STATUS_BUSY)) ) {
4119 KdPrint2((PRINT_PREFIX "ATAPI special case READY\n"));
4120 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts
4121 OurInterrupt = INTERRUPT_REASON_OUR;
4122 } else
4123 if((statusByte & (IDE_STATUS_BUSY | IDE_STATUS_DRDY)) == (IDE_STATUS_BUSY | IDE_STATUS_DRDY) ) {
4124 KdPrint2((PRINT_PREFIX "ATAPI special case pre ERR-READY\n"));
4125 OurInterrupt = INTERRUPT_REASON_OUR;
4126 } else
4127 if(statusByte & IDE_STATUS_ERROR) {
4128 KdPrint2((PRINT_PREFIX "ATAPI special case ERR-READY\n"));
4129 OurInterrupt = INTERRUPT_REASON_OUR;
4130 } else {
4131 KdPrint2((PRINT_PREFIX "ATAPI special case ? %x\n", statusByte));
4132 OurInterrupt = INTERRUPT_REASON_OUR;
4133 }
4134 }
4135 return OurInterrupt;
4136 }
4137
4138 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
4139 DmaTransfer = TRUE;
4140 KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = TRUE\n", deviceExtension->DevIndex,
4141 deviceExtension->Channel + c, c));
4142 } else {
4143 KdPrint2((PRINT_PREFIX " cntrlr %#x:%#x, lch %#x DmaTransfer = FALSE\n", deviceExtension->DevIndex,
4144 deviceExtension->Channel + c, c));
4145 dma_status = GetDmaStatus(deviceExtension, lChannel);
4146 KdPrint2((PRINT_PREFIX " DMA status %#x\n", dma_status));
4147 }
4148
4149 // do controller-specific interrupt servicing staff
4150 if(deviceExtension->UnknownDev) {
4151 KdPrint2((PRINT_PREFIX " UnknownDev\n"));
4152 goto check_unknown;
4153 }
4154
4155 // Attention !
4156 // We can catch (BM_STATUS_ACTIVE + BM_STATUS_INTR) when operation is actually completed
4157 // Such behavior was observed with Intel ICH-xxx chips
4158 // This condition shall also be treated as 'our interrupt' because of BM_STATUS_INTR flag
4159
4160 switch(VendorID) {
4161
4162 case ATA_PROMISE_ID: {
4163 switch(ChipType) {
4164 case PROLD:
4165 case PRNEW:
4166 status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x1c);
4167 if (!DmaTransfer)
4168 break;
4169 if (!(status &
4170 ((Channel) ? 0x00004000 : 0x00000400))) {
4171 KdPrint2((PRINT_PREFIX " Promise old/new unexpected\n"));
4172 return INTERRUPT_REASON_IGNORE;
4173 }
4174 break;
4175 case PRTX:
4176 AtapiWritePort1(chan, IDX_BM_DeviceSpecific0, 0x0b);
4177 status = AtapiReadPort1(chan, IDX_BM_DeviceSpecific1);
4178 if (!DmaTransfer)
4179 break;
4180 if(!(status & 0x20)) {
4181 KdPrint2((PRINT_PREFIX " Promise tx unexpected\n"));
4182 return INTERRUPT_REASON_IGNORE;
4183 }
4184 break;
4185 case PRMIO:
4186 status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x0040);
4187 if(ChipFlags & PRSATA) {
4188 pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c);
4189 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x006c, pr_status & 0x000000ff);
4190 }
4191 if(pr_status & (0x11 << Channel)) {
4192 // TODO: reset channel
4193 KdPrint2((PRINT_PREFIX " Promise mio unexpected + reset req\n"));
4194 return INTERRUPT_REASON_IGNORE;
4195 }
4196 if(!(status & (0x01 << Channel))) {
4197 KdPrint2((PRINT_PREFIX " Promise mio unexpected\n"));
4198 return INTERRUPT_REASON_IGNORE;
4199 }
4200 AtapiWritePort4(chan, IDX_BM_DeviceSpecific0, 0x00000001);
4201 break;
4202 }
4203 break; }
4204 case ATA_NVIDIA_ID: {
4205 if(!(ChipFlags & UNIATA_SATA))
4206 break;
4207
4208 KdPrint2((PRINT_PREFIX "NVIDIA\n"));
4209
4210 ULONG offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
4211 ULONG shift = Channel << ((ChipFlags & NVQ) ? 4 : 2);
4212
4213 /* get and clear interrupt status */
4214 if(ChipFlags & NVQ) {
4215 pr_status = AtapiReadPortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
4216 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0fUL << shift) | 0x00f000f0);
4217 } else {
4218 pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs);
4219 AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift));
4220 }
4221 KdPrint2((PRINT_PREFIX " pr_status %x\n", pr_status));
4222
4223 /* check for and handle connect events */
4224 if(((pr_status & (0x0cUL << shift)) == (0x04UL << shift)) ) {
4225 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, 0);
4226 }
4227 /* check for and handle disconnect events */
4228 if((pr_status & (0x08UL << shift)) &&
4229 !((pr_status & (0x04UL << shift) &&
4230 UniataSataReadPort4(chan, IDX_SATA_SStatus, 0))) ) {
4231 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, 0);
4232 }
4233 /* do we have any device action ? */
4234 if(!(pr_status & (0x01UL << shift))) {
4235 KdPrint2((PRINT_PREFIX " nVidia unexpected\n"));
4236 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4237 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4238 } else {
4239 return INTERRUPT_REASON_IGNORE;
4240 }
4241 }
4242
4243 break; }
4244 case ATA_ATI_ID:
4245 KdPrint2((PRINT_PREFIX "ATI\n"));
4246 if(ChipType == SIIMIO) {
4247 // fall to SiI
4248 } else {
4249 break;
4250 }
4251 case ATA_SILICON_IMAGE_ID:
4252
4253 if(ChipType == SIIMIO) {
4254
4255 reg32 = AtapiReadPort4(chan, IDX_BM_DeviceSpecific0);
4256 KdPrint2((PRINT_PREFIX " Sii DS0 %x\n", reg32));
4257 if(reg32 == 0xffffffff) {
4258 KdPrint2((PRINT_PREFIX " Sii mio unexpected\n"));
4259 return INTERRUPT_REASON_IGNORE;
4260 }
4261 if(!(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_DMA_COMPLETE | BM_DS0_SII_IRQ | BM_DS0_SII_DMA_ENABLE | BM_DS0_SII_DMA_ERROR))) {
4262 KdPrint2((PRINT_PREFIX " Sii mio unexpected (2)\n"));
4263 return INTERRUPT_REASON_IGNORE;
4264 }
4265
4266 if(ChipFlags & UNIATA_SATA) {
4267 if(reg32 & (BM_DS0_SII_DMA_SATA_IRQ | BM_DS0_SII_IRQ)) {
4268
4269 /* SIEN doesn't mask SATA IRQs on some 3112s. Those
4270 * controllers continue to assert IRQ as long as
4271 * SError bits are pending. Clear SError immediately.
4272 */
4273 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4274 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4275 }
4276 }
4277 }
4278
4279 if (!DmaTransfer)
4280 break;
4281 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4282 KdPrint2((PRINT_PREFIX " Sii mio unexpected (3)\n"));
4283 return OurInterrupt;
4284 }
4285 AtapiWritePort1(chan, IDX_BM_Status, dma_status & ~BM_STATUS_ERR);
4286 goto skip_dma_stat_check;
4287
4288 } else {
4289 if(!(deviceExtension->HwFlags & SIIINTR))
4290 break;
4291 GetPciConfig1(0x71, reg8);
4292 KdPrint2((PRINT_PREFIX " 0x71 = %#x\n", reg8));
4293 if (!(reg8 &
4294 (Channel ? 0x08 : 0x04))) {
4295 return INTERRUPT_REASON_IGNORE;
4296 }
4297 if (!DmaTransfer) {
4298 KdPrint2((PRINT_PREFIX " cmd our\n"));
4299 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4300 }
4301 SetPciConfig1(0x71, (Channel ? 0x08 : 0x04));
4302 }
4303 break;
4304
4305 case ATA_ACARD_ID:
4306 if (!DmaTransfer)
4307 break;
4308 //dma_status = GetDmaStatus(deviceExtension, lChannel);
4309 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4310 KdPrint2((PRINT_PREFIX " Acard unexpected\n"));
4311 return INTERRUPT_REASON_IGNORE;
4312 }
4313 AtapiWritePort1(chan, IDX_BM_Status, dma_status | BM_STATUS_INTR);
4314 AtapiStallExecution(1);
4315 AtapiWritePort1(chan, IDX_BM_Command,
4316 AtapiReadPort1(chan, IDX_BM_Command) & ~BM_COMMAND_START_STOP);
4317 goto skip_dma_stat_check;
4318 case ATA_INTEL_ID:
4319 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4320 if(ChipFlags & UNIATA_AHCI) {
4321 // Do nothing here
4322 } else
4323 if(ChipFlags & UNIATA_SATA) {
4324 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4325 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4326 }
4327 if(!(chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE)) {
4328 if(UniataSataClearErr(chan->DeviceExtension, chan->lChannel, UNIATA_SATA_IGNORE_CONNECT, 1)) {
4329 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4330 }
4331 }
4332 }
4333 }
4334 break;
4335 default:
4336 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
4337 if(ChipFlags & UNIATA_AHCI) {
4338 // Do nothing here
4339 } else
4340 if(ChipFlags & UNIATA_SATA) {
4341 if(UniataSataClearErr(HwDeviceExtension, c, UNIATA_SATA_DO_CONNECT, 0)) {
4342 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4343 }
4344 }
4345 }
4346 }
4347 check_unknown:
4348 KdPrint2((PRINT_PREFIX " perform generic check\n"));
4349 if (DmaTransfer) {
4350 if (!((dma_status = GetDmaStatus(deviceExtension, lChannel)) & BM_STATUS_INTR)) {
4351 KdPrint2((PRINT_PREFIX " DmaTransfer + !BM_STATUS_INTR (%x)\n", dma_status));
4352 if(dma_status & BM_STATUS_ERR) {
4353 KdPrint2((PRINT_PREFIX " DmaTransfer + BM_STATUS_ERR -> our\n"));
4354 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4355 } else {
4356 KdPrint2((PRINT_PREFIX " getting status...\n"));
4357 GetStatus(chan, statusByte);
4358 StatusValid = 1;
4359 KdPrint2((PRINT_PREFIX " status %#x\n", statusByte));
4360 if(statusByte & IDE_STATUS_ERROR) {
4361 KdPrint2((PRINT_PREFIX " IDE_STATUS_ERROR -> our\n", statusByte));
4362 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4363 } else
4364 if ((statusByte & IDE_STATUS_DSC) &&
4365 (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
4366 (dma_status == BM_STATUS_ACTIVE)) {
4367 KdPrint2((PRINT_PREFIX " special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte));
4368 // some devices interrupts on each block transfer even in DMA mode
4369 if(LunExt->TransferMode >= ATA_SDMA && LunExt->TransferMode <= ATA_WDMA2) {
4370 KdPrint2((PRINT_PREFIX " wait for completion\n"));
4371 ///* clear interrupt and get status */
4372 //GetBaseStatus(chan, statusByte);
4373 //return INTERRUPT_REASON_IGNORE;
4374 SingleBlockIntr = TRUE;
4375 }
4376 } else {
4377 return INTERRUPT_REASON_IGNORE;
4378 }
4379 }
4380 }
4381 } else {
4382 if(dma_status & BM_STATUS_INTR) {
4383 // bullshit, we have DMA interrupt, but had never initiate DMA operation
4384 KdPrint2((PRINT_PREFIX " clear unexpected DMA intr\n"));
4385 AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
4386 // catch it !
4387 OurInterrupt = INTERRUPT_REASON_UNEXPECTED;
4388 }
4389 }
4390 skip_dma_stat_check:
4391 if(!(ChipFlags & UNIATA_SATA) && chan->ExpectingInterrupt) {
4392 AtapiStallExecution(1);
4393 }
4394
4395 /* if drive is busy it didn't interrupt */
4396 /* the exception is DCS + BSY state of ATAPI devices */
4397 if(!StatusValid) {
4398 KdPrint2((PRINT_PREFIX " getting status...\n"));
4399 GetStatus(chan, statusByte);
4400 }
4401 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4402 KdPrint3((PRINT_PREFIX " ATAPI status %#x\n", statusByte));
4403 } else {
4404 KdPrint2((PRINT_PREFIX " IDE status %#x\n", statusByte));
4405 }
4406 if (statusByte == IDE_STATUS_WRONG) {
4407 // interrupt from empty controller ?
4408 } else
4409 if (statusByte & IDE_STATUS_BUSY) {
4410 if(!chan->ExpectingInterrupt) {
4411 KdPrint3((PRINT_PREFIX " unexpected intr + BUSY\n"));
4412 return OurInterrupt;
4413 }
4414
4415 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4416 KdPrint2((PRINT_PREFIX " ATAPI additional check\n"));
4417 } else {
4418 KdPrint2((PRINT_PREFIX " expecting intr + BUSY (3), non ATAPI\n"));
4419 return INTERRUPT_REASON_IGNORE;
4420 }
4421 if((statusByte & ~IDE_STATUS_DRQ) != (IDE_STATUS_BUSY | IDE_STATUS_DRDY | IDE_STATUS_DSC)) {
4422 KdPrint3((PRINT_PREFIX " unexpected status, seems it is not our\n"));
4423 return INTERRUPT_REASON_IGNORE;
4424 }
4425 if(!(LunExt->DeviceFlags & DFLAGS_INT_DRQ) && (statusByte & IDE_STATUS_DRQ)) {
4426 KdPrint3((PRINT_PREFIX " unexpected DRQ, seems it is not our\n"));
4427 return INTERRUPT_REASON_IGNORE;
4428 }
4429
4430 EarlyIntr = TRUE;
4431
4432 if(dma_status & BM_STATUS_INTR) {
4433 KdPrint3((PRINT_PREFIX " our interrupt with BSY set, try wait in ISR or post to DPC\n"));
4434 /* clear interrupt and get status */
4435 GetBaseStatus(chan, statusByte);
4436 if(!(dma_status & BM_STATUS_ACTIVE)) {
4437 AtapiDmaDone(deviceExtension, DEVNUM_NOT_SPECIFIED ,lChannel, NULL);
4438 }
4439 KdPrint3((PRINT_PREFIX " base status %#x (+BM_STATUS_INTR)\n", statusByte));
4440 return INTERRUPT_REASON_OUR;
4441 }
4442
4443 if(g_WaitBusyInISR) {
4444 GetStatus(chan, statusByte);
4445 KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
4446 reg8 = AtapiReadPort1(chan, IDX_IO1_i_Error);
4447 KdPrint2((PRINT_PREFIX " Error reg (%#x)\n", reg8));
4448 if (!(statusByte & IDE_STATUS_BUSY)) {
4449 KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
4450 }
4451 if (statusByte & IDE_STATUS_BUSY) {
4452 KdPrint2((PRINT_PREFIX " still BUSY, seems it is not our\n"));
4453 return INTERRUPT_REASON_IGNORE;
4454 }
4455 }
4456
4457 }
4458
4459 /* clear interrupt and get status */
4460 GetBaseStatus(chan, statusByte);
4461 KdPrint2((PRINT_PREFIX " base status %#x\n", statusByte));
4462 if (statusByte == IDE_STATUS_WRONG) {
4463 // interrupt from empty controller ?
4464 } else
4465 if(!(statusByte & (IDE_STATUS_DRQ | IDE_STATUS_DRDY))) {
4466 KdPrint2((PRINT_PREFIX " no DRQ/DRDY set\n"));
4467 return OurInterrupt;
4468 }
4469
4470 #ifndef UNIATA_PIO_ONLY
4471 if(DmaTransfer) {
4472 if(!SingleBlockIntr && (!EarlyIntr || g_WaitBusyInISR)) {
4473 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
4474 } else {
4475 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
4476 PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
4477
4478 //ASSERT(AtaReq);
4479
4480 if(SingleBlockIntr) {
4481 KdPrint2((PRINT_PREFIX " set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n"));
4482 } else {
4483 KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n"));
4484 }
4485 if(AtaReq) {
4486 AtaReq->ReqState = SingleBlockIntr ? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 : REQ_STATE_EARLY_INTR;
4487 }
4488 }
4489 }
4490 #endif //
4491
4492 if (!(chan->ExpectingInterrupt)) {
4493
4494 KdPrint2((PRINT_PREFIX " Unexpected interrupt.\n"));
4495
4496 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
4497 KdPrint2((PRINT_PREFIX " ATAPI additional check\n"));
4498 } else {
4499 KdPrint2((PRINT_PREFIX " OurInterrupt = %d\n", OurInterrupt));
4500 return OurInterrupt;
4501 }
4502 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
4503 KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason));
4504 return OurInterrupt;
4505 }
4506 //ASSERT(!chan->queue_depth || chan->cur_req);
4507
4508 KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__: exit with TRUE\n"));
4509 return INTERRUPT_REASON_OUR;
4510
4511 } // end AtapiCheckInterrupt__()
4512
4513
4514 BOOLEAN
4515 NTAPI
4516 AtapiInterrupt__(
4517 IN PVOID HwDeviceExtension,
4518 IN UCHAR c
4519 )
4520 {
4521 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
4522 PHW_CHANNEL chan = &(deviceExtension->chan[c]);
4523 // Get current Srb
4524 PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan);
4525 PATA_REQ AtaReq = srb ? (PATA_REQ)(srb->SrbExtension) : NULL;
4526
4527 ULONG wordCount = 0, wordsThisInterrupt = DEV_BSIZE/2;
4528 ULONG status = SRB_STATUS_SUCCESS;
4529 UCHAR dma_status = 0;
4530 ULONG i;
4531 ULONG k;
4532 UCHAR statusByte = 0,interruptReason;
4533
4534 BOOLEAN atapiDev = FALSE;
4535
4536 UCHAR Channel;
4537 UCHAR lChannel;
4538 UCHAR DeviceNumber;
4539 BOOLEAN DmaTransfer = FALSE;
4540 UCHAR error = 0;
4541 ULONG TimerValue = 1000;
4542 ULONG TotalTimerValue = 0;
4543 #ifdef UNIATA_USE_XXableInterrupts
4544 BOOLEAN InDpc = (KeGetCurrentIrql() == DISPATCH_LEVEL);
4545 #else
4546 BOOLEAN InDpc = (chan->DpcState != DPC_STATE_ISR);
4547 #endif // UNIATA_USE_XXableInterrupts
4548 BOOLEAN UseDpc = deviceExtension->UseDpc;
4549 // BOOLEAN RestoreUseDpc = FALSE;
4550 BOOLEAN DataOverrun = FALSE;
4551 BOOLEAN NoStartIo = TRUE;
4552
4553 KdPrint2((PRINT_PREFIX "AtapiInterrupt:\n"));
4554 if(InDpc) {
4555 KdPrint2((PRINT_PREFIX " InDpc = TRUE\n"));
4556 //ASSERT((chan->ChannelCtrlFlags & CTRFLAGS_INTR_DISABLED));
4557 }
4558
4559 UCHAR PathId;
4560 UCHAR TargetId;
4561 UCHAR Lun;
4562 UCHAR OldReqState = REQ_STATE_NONE;
4563 //ULONG ldev;
4564 PHW_LU_EXTENSION LunExt;
4565
4566 lChannel = c;
4567 Channel = (UCHAR)(deviceExtension->Channel + lChannel);
4568
4569 KdPrint2((PRINT_PREFIX " cntrlr %#x:%d, irql %#x, c %d\n", deviceExtension->DevIndex, Channel, KeGetCurrentIrql(), c));
4570
4571 if((chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) ||
4572 (AtaReq && (AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) ||
4573 (deviceExtension->HwFlags & UNIATA_AHCI)) {
4574 DmaTransfer = TRUE;
4575 KdPrint2((PRINT_PREFIX " DmaTransfer = TRUE\n"));
4576 }
4577
4578 if (srb) {
4579 PathId = srb->PathId;
4580 TargetId = srb->TargetId;
4581 Lun = srb->Lun;
4582 } else {
4583 PathId = (UCHAR)c;
4584 TargetId =
4585 Lun = 0;
4586 goto enqueue_next_req;
4587 }
4588
4589 //ldev = GET_LDEV2(PathId, TargetId, Lun);
4590 DeviceNumber = (UCHAR)(TargetId);
4591 LunExt = chan->lun[DeviceNumber];
4592 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
4593 KdPrint2((PRINT_PREFIX " dev_type %s\n", atapiDev ? "ATAPI" : "IDE"));
4594
4595 // check if we are in ISR DPC
4596 if(InDpc) {
4597 KdPrint2((PRINT_PREFIX " InDpc -> CTRFLAGS_INTR_DISABLED\n"));
4598 goto ServiceInterrupt;
4599 }
4600
4601 if (DmaTransfer) {
4602 dma_status = GetDmaStatus(deviceExtension, lChannel);
4603 }
4604
4605 if (!(chan->ExpectingInterrupt)) {
4606
4607 KdPrint2((PRINT_PREFIX " Unexpected interrupt for this channel.\n"));
4608 return FALSE;
4609 }
4610
4611 // change request state
4612 if(AtaReq) {
4613 OldReqState = AtaReq->ReqState;
4614 AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
4615 KdPrint2((PRINT_PREFIX " OldReqState = %x\n", OldReqState));
4616 }
4617
4618 // We don't want using DPC for fast operations, like
4619 // DMA completion, sending CDB, short ATAPI transfers, etc.
4620 // !!!! BUT !!!!
4621 // We MUST use DPC, because of interprocessor synchronization
4622 // on multiprocessor platforms
4623
4624 if(DmaTransfer)
4625 goto ServiceInterrupt;
4626
4627 switch(OldReqState) {
4628 case REQ_STATE_ATAPI_EXPECTING_CMD_INTR:
4629 KdPrint3((PRINT_PREFIX " EXPECTING_CMD_INTR\n"));
4630 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR:
4631 case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2:
4632 case REQ_STATE_DPC_WAIT_BUSY0:
4633 case REQ_STATE_DPC_WAIT_BUSY1:
4634 KdPrint2((PRINT_PREFIX " continue service interrupt\n"));
4635 goto ServiceInterrupt;
4636 case REQ_STATE_ATAPI_DO_NOTHING_INTR:
4637 KdPrint2((PRINT_PREFIX " do nothing on interrupt\n"));
4638 return TRUE;
4639 }
4640
4641 if(!DmaTransfer && !atapiDev) {
4642 KdPrint2((PRINT_PREFIX " service PIO HDD\n"));
4643 UseDpc = FALSE;
4644 }
4645
4646 #ifndef UNIATA_CORE
4647
4648 if(!UseDpc)
4649 goto ServiceInterrupt;
4650
4651 #ifdef UNIATA_USE_XXableInterrupts
4652 if(InDpc) {
4653 KdPrint2((PRINT_PREFIX " Unexpected InDpc\n"));
4654 ASSERT(FALSE);
4655 // shall never get here
4656 TimerValue = 1;
4657 goto CallTimerDpc;
4658 }
4659
4660 KdPrint2((PRINT_PREFIX " this is direct DPC call on DRQL\n"));
4661 if(AtaReq) {
4662 AtaReq->ReqState = REQ_STATE_DPC_INTR_REQ;
4663 KdPrint2((PRINT_PREFIX " ReqState -> REQ_STATE_DPC_INTR_REQ\n"));
4664 } else {
4665 KdPrint2((PRINT_PREFIX " DPC without AtaReq!!!\n"));
4666 }
4667 #else
4668 KdPrint2((PRINT_PREFIX "call service interrupt\n"));
4669 goto ServiceInterrupt;
4670 #endif // UNIATA_USE_XXableInterrupts
4671
4672 PostToDpc:
4673
4674 // Attention !!!
4675 // AtapiInterruptDpc() is called on DISPATCH_LEVEL
4676 // We always get here when are called from timer callback, which is invoked on DRQL.
4677 // It is intended to lower IRQL and let other interrupts to be serviced while we are waiting for BUSY release
4678
4679 KdPrint2((PRINT_PREFIX "AtapiInterrupt: start DPC init...\n"));
4680 // disable interrupts for this channel,
4681 // but avoid recursion and double-disable
4682 if(OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
4683 UniataExpectChannelInterrupt(chan, FALSE);
4684 AtapiDisableInterrupts(deviceExtension, lChannel);
4685 }
4686 // go to ISR DPC
4687 chan->ChannelCtrlFlags |= CTRFLAGS_DPC_REQ;
4688
4689 #ifdef UNIATA_USE_XXableInterrupts
4690 // Will lower IRQL to DISPATCH_LEVEL
4691 ScsiPortNotification(CallEnableInterrupts, HwDeviceExtension,
4692 /*c ?*/ AtapiInterruptDpc/*_1 : AtapiInterruptDpc_0*/);
4693 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DPC inited\n"));
4694 #else
4695 // Will raise IRQL to DIRQL
4696 AtapiQueueTimerDpc(HwDeviceExtension, c,
4697 AtapiInterruptDpc,
4698 TimerValue);
4699 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
4700 #endif // UNIATA_USE_XXableInterrupts
4701 return TRUE;
4702
4703 #ifndef UNIATA_CORE
4704 CallTimerDpc:
4705 AtaReq->ReqState = REQ_STATE_PROCESSING_INTR;
4706 CallTimerDpc2:
4707 if(!InDpc && OldReqState != REQ_STATE_DPC_WAIT_BUSY1) {
4708 // we must block interrupts from this channel
4709 // If device generate new interrupt before we get to DPC,
4710 // ISR will assume, that it is NOT our interrupt
4711 AtapiDisableInterrupts(deviceExtension, lChannel);
4712 // We should not clean ExpectingInterrupt flag on channel, since it is used in DPC
4713 }
4714 // Will raise IRQL to DIRQL
4715 AtapiQueueTimerDpc(HwDeviceExtension, c,
4716 AtapiCallBack_X,
4717 TimerValue);
4718 return TRUE;
4719 #endif //UNIATA_CORE
4720
4721 ServiceInterrupt:
4722
4723 if(AtaReq && InDpc) {
4724 switch(AtaReq->ReqState) {
4725 case REQ_STATE_DPC_WAIT_DRQ0:
4726 goto PIO_wait_DRQ0;
4727 case REQ_STATE_DPC_WAIT_BUSY:
4728 goto PIO_wait_busy;
4729 case REQ_STATE_DPC_WAIT_DRQ:
4730 goto PIO_wait_DRQ;
4731 case REQ_STATE_DPC_WAIT_DRQ_ERR:
4732 goto continue_err;
4733 case REQ_STATE_DPC_WAIT_BUSY0:
4734 case REQ_STATE_DPC_WAIT_BUSY1:
4735 // continue normal execution
4736 break;
4737 }
4738 }
4739 #else
4740 ServiceInterrupt:
4741 #endif //UNIATA_CORE
4742 /*
4743 // make additional delay for old devices (if we are not in DPC)
4744 if((!LunExt->IdentifyData.MajorRevision || (deviceExtension->lun[DeviceNumber].TransferMode < ATA_PIO4))
4745 &&
4746 !InDpc &&
4747 !atapiDev &&
4748 !(deviceExtension->HwFlags & UNIATA_SATA)
4749 ) {
4750 KdPrint2((PRINT_PREFIX " additional delay 10us for old devices\n"));
4751 AtapiStallExecution(10);
4752 }
4753 */
4754
4755 /* clear interrupt and get status */
4756 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4757 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, srb);
4758 statusByte = (UCHAR)(AtaReq->ahci.in_status & IDE_STATUS_MASK);
4759
4760 if(chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB)) {
4761 KdPrint3((PRINT_PREFIX "Err intr (%#x)\n", chan->AhciLastIS & ~(ATA_AHCI_P_IX_DHR | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_SDB)));
4762 if(chan->AhciLastIS & ~ATA_AHCI_P_IX_OF) {
4763 //KdPrint3((PRINT_PREFIX "Err mask (%#x)\n", chan->AhciLastIS & ~ATA_AHCI_P_IX_OF));
4764 // We have some other error except Overflow
4765 // Just signal ERROR, operation will be aborted in ERROR branch.
4766 statusByte |= IDE_STATUS_ERROR;
4767 } else {
4768 // We have only Overflow. Abort operation and continue
4769 #if DBG
4770 UniataDumpAhciPortRegs(chan);
4771 #endif
4772 if(!UniataAhciAbortOperation(chan)) {
4773 KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
4774 }
4775 #if DBG
4776 UniataDumpAhciPortRegs(chan);
4777 #endif
4778 UniataAhciWaitCommandReady(chan, 10);
4779 }
4780 }
4781
4782 } else {
4783 GetBaseStatus(chan, statusByte);
4784 }
4785 if(atapiDev) {
4786 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Entered with status (%#x)\n", statusByte));
4787 } else {
4788 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Entered with status (%#x)\n", statusByte));
4789 }
4790
4791 if(!UseDpc) {
4792 KdPrint2((PRINT_PREFIX " operate like in DPC\n"));
4793 InDpc = TRUE;
4794 }
4795
4796 if (!atapiDev) {
4797 // IDE
4798 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4799 KdPrint3((PRINT_PREFIX " AHCI branch (IDE)\n"));
4800 } else
4801 if (statusByte & IDE_STATUS_BUSY) {
4802 if (deviceExtension->DriverMustPoll) {
4803 // Crashdump is polling and we got caught with busy asserted.
4804 // Just go away, and we will be polled again shortly.
4805 KdPrint2((PRINT_PREFIX " Hit BUSY while polling during crashdump.\n"));
4806 goto ReturnEnableIntr;
4807 }
4808 try_dpc_wait:
4809 // Ensure BUSY is non-asserted.
4810 // make a very small idle before falling to DPC
4811 k = (InDpc && UseDpc) ? 1000 : 2;
4812
4813 for (i = 0; i < k; i++) {
4814
4815 GetBaseStatus(chan, statusByte);
4816 if (!(statusByte & IDE_STATUS_BUSY)) {
4817 break;
4818 }
4819 AtapiStallExecution(10);
4820 }
4821
4822 if (!InDpc && UseDpc && i == 2) {
4823
4824 KdPrint2((PRINT_PREFIX " BUSY on entry. Status %#x, Base IO %#x\n", statusByte));
4825
4826 TimerValue = 50;
4827 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
4828
4829 #ifndef UNIATA_CORE
4830 goto PostToDpc;
4831 #else //UNIATA_CORE
4832 AtapiStallExecution(TimerValue);
4833 goto ServiceInterrupt;
4834 #endif //UNIATA_CORE
4835 } else
4836 if (InDpc && i == k) {
4837 // reset the controller.
4838 KdPrint2((PRINT_PREFIX
4839 " Resetting due to BUSY on entry - %#x.\n",
4840 statusByte));
4841 goto IntrPrepareResetController;
4842 }
4843 }
4844 } else {
4845 // ATAPI
4846 if(!LunExt->IdentifyData.MajorRevision &&
4847 InDpc &&
4848 /*!atapiDev &&*/
4849 !(deviceExtension->HwFlags & UNIATA_SATA)
4850 ) {
4851 //KdPrint2((PRINT_PREFIX " additional delay 10us for old devices (2)\n"));
4852 //AtapiStallExecution(10);
4853 }
4854 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4855 KdPrint3((PRINT_PREFIX " AHCI branch (ATAPI)\n"));
4856 } else {
4857 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
4858 KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
4859 }
4860
4861 if (statusByte & IDE_STATUS_BUSY) {
4862 //if(chan->ChannelCtrlFlags & CTRFLAGS_DSC_BSY) {}
4863 /*
4864 #ifndef UNIATA_CORE
4865 // This is just workaround
4866 // We should DISABLE interrupts before entering WAIT state
4867 UniataExpectChannelInterrupt(chan, TRUE);
4868 #endif //UNIATA_CORE
4869 */
4870 KdPrint3((PRINT_PREFIX " BUSY on ATAPI device, waiting %d us\n", LunExt->AtapiReadyWaitDelay));
4871 #ifndef UNIATA_CORE
4872 if(LunExt->AtapiReadyWaitDelay && (LunExt->AtapiReadyWaitDelay > g_opt_MaxIsrWait) && !InDpc && UseDpc) {
4873 TimerValue = LunExt->AtapiReadyWaitDelay;
4874 KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC (0)\n"));
4875 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
4876 goto CallTimerDpc2;
4877 }
4878 #endif //UNIATA_CORE
4879 TimerValue = 10;
4880 for(k=20; k; k--) {
4881 GetBaseStatus(chan, statusByte);
4882 KdPrint3((PRINT_PREFIX " status re-check %#x\n", statusByte));
4883 KdPrint3((PRINT_PREFIX " Error reg (%#x)\n",
4884 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Error)));
4885 if (!(statusByte & IDE_STATUS_BUSY)) {
4886 KdPrint2((PRINT_PREFIX " expecting intr + cleared BUSY\n"));
4887 break;
4888 }
4889 TotalTimerValue += TimerValue;
4890 if(k <= 1) {
4891 KdPrint3((PRINT_PREFIX " too long wait -> DPC\n"));
4892 if(!InDpc) {
4893 KdPrint2((PRINT_PREFIX " too long wait: ISR -> DPC\n"));
4894 TimerValue = 100;
4895 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY0;
4896 } else {
4897 KdPrint2((PRINT_PREFIX " too long wait: DPC -> DPC\n"));
4898 TimerValue = 1000;
4899 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY1;
4900 }
4901 #ifndef UNIATA_CORE
4902 if(UseDpc) {
4903 if(!LunExt->AtapiReadyWaitDelay) {
4904 LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
4905 }
4906 goto CallTimerDpc2;
4907 }
4908 #endif //UNIATA_CORE
4909 }
4910
4911 AtapiStallExecution(TimerValue);
4912 TimerValue += 10;
4913 }
4914 if(!LunExt->AtapiReadyWaitDelay) {
4915 LunExt->AtapiReadyWaitDelay = TotalTimerValue*2/3;
4916 KdPrint2((PRINT_PREFIX " store AtapiReadyWaitDelay: %d\n", LunExt->AtapiReadyWaitDelay));
4917 }
4918 if (statusByte & IDE_STATUS_BUSY) {
4919 KdPrint3((PRINT_PREFIX " expecting intr + BUSY (2), try DPC wait\n"));
4920 goto try_dpc_wait;
4921 }
4922 }
4923 }
4924
4925 if(AtaReq && DmaTransfer && !(deviceExtension->HwFlags & UNIATA_AHCI)) {
4926 switch(OldReqState) {
4927 case REQ_STATE_EARLY_INTR:
4928 case REQ_STATE_DPC_WAIT_BUSY0:
4929
4930 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_ACTIVE) {
4931 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DMA still active\n"));
4932 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
4933 }
4934 break;
4935 }
4936 }
4937
4938 //retry_check:
4939 // Check for error conditions.
4940 if ((statusByte & IDE_STATUS_ERROR) ||
4941 (dma_status & BM_STATUS_ERR)) {
4942
4943 if(deviceExtension->HwFlags & UNIATA_AHCI) {
4944 error = AtaReq->ahci.in_error;
4945 // wait ready
4946 #if DBG
4947 UniataDumpAhciPortRegs(chan);
4948 #endif
4949 if(!UniataAhciAbortOperation(chan)) {
4950 KdPrint2((PRINT_PREFIX "need UniataAhciReset\n"));
4951 }
4952 // clear interrupts again
4953 UniataAhciWaitCommandReady(chan, 10);
4954 #if DBG
4955 UniataDumpAhciPortRegs(chan);
4956 #endif
4957 UniataAhciStatus(HwDeviceExtension, lChannel, DEVNUM_NOT_SPECIFIED);
4958 #if DBG
4959 UniataDumpAhciPortRegs(chan);
4960 #endif
4961 } else {
4962 error = AtapiReadPort1(chan, IDX_IO1_i_Error);
4963 }
4964 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Error %#x\n", error));
4965 /*
4966 if(error & IDE_STATUS_CORRECTED_ERROR) {
4967 KdPrint2((PRINT_PREFIX "AtapiInterrupt: (corrected)\n"));
4968 statusByte &= ~IDE_STATUS_ERROR;
4969 goto retry_check;
4970 }
4971 */
4972 if(AtaReq) {
4973 KdPrint2((PRINT_PREFIX " Bad Lba %#I64x\n", AtaReq->lba));
4974 } else {
4975 KdPrint2((PRINT_PREFIX " Bad Lba unknown\n"));
4976 }
4977
4978
4979 if(!atapiDev) {
4980 KdPrint2((PRINT_PREFIX " wait 100 ready after IDE error\n"));
4981 AtapiStallExecution(100);
4982 } else {
4983 KdPrint2((PRINT_PREFIX " wait 10 ready after ATAPI error\n"));
4984 AtapiStallExecution(10);
4985 }
4986 continue_err:
4987
4988 KdPrint3((PRINT_PREFIX " Intr on DRQ %x\n",
4989 LunExt->DeviceFlags & DFLAGS_INT_DRQ));
4990
4991 for (k = atapiDev ? 0 : 200; k; k--) {
4992 GetBaseStatus(chan, statusByte);
4993 if (!(statusByte & IDE_STATUS_DRQ)) {
4994 AtapiStallExecution(50);
4995 } else {
4996 break;
4997 }
4998 }
4999
5000 if (!atapiDev) {
5001 /* if this is a UDMA CRC error, reinject request */
5002
5003 AtaReq->retry++;
5004 if(AtaReq->retry < MAX_RETRIES) {
5005 #ifdef IO_STATISTICS
5006 chan->lun[DeviceNumber]->ModeErrorCount[AtaReq->retry]++;
5007 #endif //IO_STATISTICS
5008 if(DmaTransfer /*&&
5009 (error & IDE_ERROR_ICRC)*/) {
5010 if(AtaReq->retry < MAX_RETRIES) {
5011 //fallback_pio:
5012 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5013 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
5014 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5015 AtaReq->ReqState = REQ_STATE_QUEUED;
5016 goto reenqueue_req;
5017 }
5018 } else {
5019 if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
5020 AtaReq->retry++;
5021 }
5022 KdPrint2((PRINT_PREFIX "Errors in PIO mode\n"));
5023 }
5024 }
5025 } else {
5026 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
5027 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason));
5028
5029 if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) &&
5030 ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) {
5031 if(AtaReq->retry < MAX_RETRIES) {
5032 //fallback_pio:
5033 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5034 AtaReq->Flags |= REQ_FLAG_FORCE_DOWNRATE;
5035 // LunExt->DeviceFlags |= DFLAGS_FORCE_DOWNRATE;
5036 AtaReq->ReqState = REQ_STATE_QUEUED;
5037 goto reenqueue_req;
5038 }
5039 } else {
5040 if(!(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE)) {
5041 AtaReq->retry++;
5042 }
5043 KdPrint3((PRINT_PREFIX "Errors in PIO mode\n"));
5044 }
5045 }
5046
5047 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error\n"));
5048 if (srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
5049 // Fail this request.
5050 status = SRB_STATUS_ERROR;
5051 goto CompleteRequest;
5052 } else {
5053 KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n"));
5054 }
5055 } else
5056 if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE_LBA48) {
5057 KdPrint2((PRINT_PREFIX "DMA doesn't work right with LBA48\n"));
5058 deviceExtension->HbaCtrlFlags |= HBAFLAGS_DMA_DISABLED_LBA48;
5059 } else
5060 if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
5061 #ifdef IO_STATISTICS
5062 KdPrint2((PRINT_PREFIX "Some higher mode doesn't work right :((\n"));
5063 KdPrint2((PRINT_PREFIX "Recovery stats[%d]: %d vs %d\n",
5064 AtaReq->retry,
5065 LunExt->RecoverCount[AtaReq->retry],
5066 LunExt->BlockIoCount
5067 ));
5068 LunExt->RecoverCount[AtaReq->retry]++;
5069 if(LunExt->RecoverCount[AtaReq->retry] >= chan->lun[DeviceNumber]->BlockIoCount/3 ||
5070 (deviceExtension->HwFlags & UNIATA_NO80CHK)
5071 ) {
5072 #else
5073 if(deviceExtension->HwFlags & UNIATA_NO80CHK) {
5074 #endif //IO_STATISTICS
5075 KdPrint2((PRINT_PREFIX "Limit transfer rate to %x\n", LunExt->TransferMode));
5076 LunExt->LimitedTransferMode =
5077 LunExt->TransferMode;
5078 }
5079 }
5080 #ifdef IO_STATISTICS
5081 if(AtaReq->bcount) {
5082 // we need stats for Read/Write operations
5083 LunExt->BlockIoCount++;
5084 }
5085 LunExt->IoCount++;
5086 #endif //IO_STATISTICS
5087
5088 continue_PIO:
5089
5090 // check reason for this interrupt.
5091 if (atapiDev) {
5092
5093 KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n"));
5094 // ATAPI branch
5095
5096 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
5097 KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason));
5098 if(DmaTransfer) {
5099 wordsThisInterrupt = DEV_BSIZE/2*512;
5100 } else {
5101 wordsThisInterrupt = DEV_BSIZE/2;
5102 }
5103
5104 } else {
5105
5106 // ATA branch
5107
5108 if(DmaTransfer) {
5109 // simulate DRQ for DMA transfers
5110 statusByte |= IDE_STATUS_DRQ;
5111 }
5112 if (statusByte & IDE_STATUS_DRQ) {
5113
5114 if(DmaTransfer) {
5115 wordsThisInterrupt = DEV_BSIZE/2*512;
5116 } else
5117 if (LunExt->MaximumBlockXfer) {
5118 wordsThisInterrupt = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
5119 }
5120
5121 if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5122
5123 interruptReason = ATAPI_IR_IO_toHost;
5124
5125 } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
5126 interruptReason = ATAPI_IR_IO_toDev;
5127
5128 } else {
5129 status = SRB_STATUS_ERROR;
5130 goto CompleteRequest;
5131 }
5132
5133 } else if (statusByte & IDE_STATUS_BUSY) {
5134
5135 //AtapiEnableInterrupts(deviceExtension, lChannel);
5136 KdPrint2((PRINT_PREFIX "AtapiInterrupt: return FALSE on ATA IDE_STATUS_BUSY\n"));
5137 return FALSE;
5138
5139 } else {
5140
5141 if (AtaReq->WordsLeft) {
5142
5143 // Funky behaviour seen with PCI IDE (not all, just one).
5144 PIO_wait_DRQ0:
5145 // The ISR hits with DRQ low, but comes up later.
5146 for (k = 0; k < 5000; k++) {
5147 GetBaseStatus(chan, statusByte);
5148 if (statusByte & IDE_STATUS_DRQ) {
5149 break;
5150 }
5151 if(!InDpc) {
5152 // goto DPC
5153 AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ0;
5154 TimerValue = 100;
5155 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq0)\n"));
5156 #ifndef UNIATA_CORE
5157 goto PostToDpc;
5158 #else //UNIATA_CORE
5159 AtapiStallExecution(TimerValue);
5160 goto ServiceInterrupt;
5161 #endif //UNIATA_CORE
5162 }
5163 AtapiStallExecution(100);
5164 }
5165 if (k == 5000) {
5166 // reset the controller.
5167 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ not up. Status %#x\n",
5168 statusByte));
5169 IntrPrepareResetController:
5170 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_CURRENT);
5171 goto ReturnEnableIntr;
5172
5173 } else {
5174 interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? ATAPI_IR_IO_toHost : ATAPI_IR_IO_toDev;
5175 }
5176
5177 } else {
5178 // Command complete - verify, write, or the SMART enable/disable.
5179 // Also get_media_status
5180 interruptReason = ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd;
5181 }
5182 }
5183 }
5184
5185 KdPrint2((PRINT_PREFIX "AtapiInterrupt: i-reason=%d, status=%#x\n", interruptReason, statusByte));
5186 if(deviceExtension->HwFlags & UNIATA_AHCI) {
5187 KdPrint2((PRINT_PREFIX " AHCI path, WordsTransfered %x, WordsLeft %x\n", AtaReq->WordsTransfered, AtaReq->WordsLeft));
5188 /* if(chan->AhciLastIS & ATA_AHCI_P_IX_OF) {
5189 //status = SRB_STATUS_DATA_OVERRUN;
5190 DataOverrun = TRUE;
5191 } else {
5192 status = SRB_STATUS_SUCCESS;
5193 }*/
5194 if(AtaReq->WordsTransfered >= AtaReq->WordsLeft) {
5195 AtaReq->WordsLeft = 0;
5196 } else {
5197 AtaReq->WordsLeft -= AtaReq->WordsTransfered;
5198 }
5199 //if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5200 // status = SRB_STATUS_DATA_OVERRUN;
5201 //}
5202 status = SRB_STATUS_SUCCESS;
5203 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5204 goto CompleteRequest;
5205 } else
5206 if (interruptReason == ATAPI_IR_COD_Cmd && (statusByte & IDE_STATUS_DRQ)) {
5207 // Write the packet.
5208 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n"));
5209 // Send CDB to device.
5210 WriteBuffer(chan, (PUSHORT)srb->Cdb,
5211 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
5212 0);
5213 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5214
5215 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
5216 KdPrint2((PRINT_PREFIX "AtapiInterrupt: AtapiDmaStart().\n"));
5217 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, srb);
5218 }
5219
5220 goto ReturnEnableIntr;
5221
5222 } else if (interruptReason == ATAPI_IR_IO_toDev && (statusByte & IDE_STATUS_DRQ)) {
5223
5224 // Write the data.
5225 if (atapiDev) {
5226
5227 // Pick up bytes to transfer and convert to words.
5228 wordCount =
5229 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow);
5230
5231 wordCount |=
5232 (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8;
5233
5234 // Covert bytes to words.
5235 wordCount >>= 1;
5236 KdPrint2((PRINT_PREFIX "AtapiInterrupt: get W wordCount %#x\n", wordCount));
5237
5238 if (wordCount != AtaReq->WordsLeft) {
5239 KdPrint2((PRINT_PREFIX
5240 "AtapiInterrupt: %d words requested; %d words xferred\n",
5241 AtaReq->WordsLeft,
5242 wordCount));
5243 }
5244
5245 // Verify this makes sense.
5246 if (wordCount > AtaReq->WordsLeft) {
5247 wordCount = AtaReq->WordsLeft;
5248 KdPrint2((PRINT_PREFIX
5249 "AtapiInterrupt: Write underrun\n"));
5250 DataOverrun = TRUE;
5251 }
5252
5253 } else {
5254
5255 // IDE path. Check if words left is at least DEV_BSIZE/2 = 256.
5256 if (AtaReq->WordsLeft < wordsThisInterrupt) {
5257 // Transfer only words requested.
5258 wordCount = AtaReq->WordsLeft;
5259 } else {
5260 // Transfer next block.
5261 wordCount = wordsThisInterrupt;
5262 }
5263 }
5264
5265 if (DmaTransfer &&
5266 (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
5267 //ASSERT(AtaReq->WordsLeft == wordCount);
5268 if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
5269 KdPrint2((PRINT_PREFIX
5270 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
5271 if(AtaReq->WordsLeft > wordCount) {
5272 AtaReq->WordsLeft -= wordCount;
5273 AtaReq->WordsTransfered += wordCount;
5274 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5275 goto ReturnEnableIntr;
5276 }
5277 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
5278 }
5279 AtaReq->WordsTransfered = AtaReq->WordsLeft;
5280 AtaReq->WordsLeft = 0;
5281 status = SRB_STATUS_SUCCESS;
5282 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5283 goto CompleteRequest;
5284 }
5285
5286 // Ensure that this is a write command.
5287 if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
5288
5289 KdPrint2((PRINT_PREFIX
5290 "AtapiInterrupt: Write interrupt\n"));
5291
5292 statusByte = WaitOnBusy(chan);
5293
5294 if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
5295
5296 WriteBuffer(chan,
5297 AtaReq->DataBuffer,
5298 wordCount,
5299 UniataGetPioTiming(LunExt));
5300 } else {
5301
5302 WriteBuffer2(chan,
5303 (PULONG)(AtaReq->DataBuffer),
5304 wordCount / 2,
5305 UniataGetPioTiming(LunExt));
5306 }
5307 } else {
5308
5309 KdPrint3((PRINT_PREFIX
5310 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5311 interruptReason,
5312 srb));
5313
5314 // Fail this request.
5315 status = SRB_STATUS_ERROR;
5316 goto CompleteRequest;
5317 }
5318 // Advance data buffer pointer and bytes left.
5319 AtaReq->DataBuffer += wordCount;
5320 AtaReq->WordsLeft -= wordCount;
5321 AtaReq->WordsTransfered += wordCount;
5322
5323 if (atapiDev) {
5324 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5325 }
5326
5327 goto ReturnEnableIntr;
5328
5329 } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) {
5330
5331
5332 if (atapiDev) {
5333
5334 // Pick up bytes to transfer and convert to words.
5335 wordCount =
5336 AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow) |
5337 (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8);
5338
5339 // Convert bytes to words.
5340 wordCount >>= 1;
5341 KdPrint2((PRINT_PREFIX "AtapiInterrupt: get R wordCount %#x\n", wordCount));
5342
5343 if (wordCount != AtaReq->WordsLeft) {
5344 KdPrint2((PRINT_PREFIX
5345 "AtapiInterrupt: %d words requested; %d words xferred\n",
5346 AtaReq->WordsLeft,
5347 wordCount));
5348 }
5349
5350 // Verify this makes sense.
5351 if (wordCount > AtaReq->WordsLeft) {
5352 wordCount = AtaReq->WordsLeft;
5353 DataOverrun = TRUE;
5354 }
5355
5356 } else {
5357
5358 // Check if words left is at least 256.
5359 if (AtaReq->WordsLeft < wordsThisInterrupt) {
5360 // Transfer only words requested.
5361 wordCount = AtaReq->WordsLeft;
5362 } else {
5363 // Transfer next block.
5364 wordCount = wordsThisInterrupt;
5365 }
5366 }
5367
5368 if(DmaTransfer &&
5369 (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) {
5370 if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) {
5371 KdPrint2((PRINT_PREFIX
5372 "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount));
5373 if(AtaReq->WordsLeft > wordCount) {
5374 AtaReq->WordsLeft -= wordCount;
5375 AtaReq->WordsTransfered += wordCount;
5376 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5377 goto ReturnEnableIntr;
5378 }
5379 dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/);
5380 }
5381 //ASSERT(AtaReq->WordsLeft == wordCount);
5382 AtaReq->WordsTransfered = AtaReq->WordsLeft;
5383 AtaReq->WordsLeft = 0;
5384 status = SRB_STATUS_SUCCESS;
5385 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
5386 goto CompleteRequest;
5387 }
5388 // Ensure that this is a read command.
5389 if (srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5390
5391 /* KdPrint2((
5392 "AtapiInterrupt: Read interrupt\n"));*/
5393
5394 statusByte = WaitOnBusy(chan);
5395
5396 if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
5397 KdPrint2((PRINT_PREFIX
5398 "IdeIntr: Read %#x words\n", wordCount));
5399
5400 ReadBuffer(chan,
5401 AtaReq->DataBuffer,
5402 wordCount,
5403 UniataGetPioTiming(LunExt));
5404 KdPrint2(("IdeIntr: PIO Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x\n", AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)-1) ));
5405 //KdDump(AtaReq->DataBuffer, wordCount*2);
5406 if(srb && atapiDev && srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
5407 KdDump(AtaReq->DataBuffer, wordCount*2);
5408 }
5409
5410 GetBaseStatus(chan, statusByte);
5411 KdPrint2((PRINT_PREFIX " status re-check %#x\n", statusByte));
5412
5413 if(DataOverrun) {
5414 KdPrint2((PRINT_PREFIX " DataOverrun\n"));
5415 AtapiSuckPort2(chan);
5416 GetBaseStatus(chan, statusByte);
5417 }
5418
5419 if(statusByte & IDE_STATUS_BUSY) {
5420 for (i = 0; i < 2; i++) {
5421 AtapiStallExecution(10);
5422 GetBaseStatus(chan, statusByte);
5423 if (!(statusByte & IDE_STATUS_BUSY)) {
5424 break;
5425 }
5426 }
5427 }
5428
5429 } else {
5430 KdPrint2((PRINT_PREFIX
5431 "IdeIntr: Read %#x Dwords\n", wordCount/2));
5432
5433 ReadBuffer2(chan,
5434 (PULONG)(AtaReq->DataBuffer),
5435 wordCount / 2,
5436 UniataGetPioTiming(LunExt));
5437 }
5438 } else {
5439
5440 KdPrint3((PRINT_PREFIX
5441 "AtapiInterrupt: Int reason %#x, but srb is for a read %#x.\n",
5442 interruptReason,
5443 srb));
5444
5445 // Fail this request.
5446 status = SRB_STATUS_ERROR;
5447 goto CompleteRequest;
5448 }
5449
5450 // Advance data buffer pointer and bytes left.
5451 AtaReq->DataBuffer += wordCount;
5452 AtaReq->WordsLeft -= wordCount;
5453 AtaReq->WordsTransfered += wordCount;
5454
5455 // Check for read command complete.
5456 if (AtaReq->WordsLeft == 0) {
5457
5458 KdPrint2((PRINT_PREFIX "AtapiInterrupt: all transferred, AtaReq->WordsLeft == 0\n"));
5459 if (atapiDev) {
5460
5461 // Work around to make many atapi devices return correct sector size
5462 // of 2048. Also certain devices will have sector count == 0x00, check
5463 // for that also.
5464 if ((srb->Cdb[0] == SCSIOP_READ_CAPACITY) &&
5465 (LunExt->IdentifyData.DeviceType == ATAPI_TYPE_CDROM)) {
5466
5467 AtaReq->DataBuffer -= wordCount;
5468 if (AtaReq->DataBuffer[0] == 0x00) {
5469
5470 *((ULONG *) &(AtaReq->DataBuffer[0])) = 0xFFFFFF7F;
5471
5472 }
5473
5474 *((ULONG *) &(AtaReq->DataBuffer[2])) = 0x00080000;
5475 AtaReq->DataBuffer += wordCount;
5476 }
5477
5478 GetStatus(chan, statusByte);
5479 if(!(statusByte & IDE_STATUS_BUSY)) {
5480 // Assume command is completed if BUSY is cleared
5481 // and all data read
5482 // Optionally, we may receive COMPLETE interrupt later and
5483 // treat it as unexpected
5484 KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete ? status %x\n", statusByte));
5485
5486 status = SRB_STATUS_SUCCESS;
5487 goto CompleteRequest;
5488 }
5489
5490 } else {
5491
5492 /*
5493 // Completion for IDE drives.
5494 if (AtaReq->WordsLeft) {
5495 status = SRB_STATUS_DATA_OVERRUN;
5496 } else {
5497 status = SRB_STATUS_SUCCESS;
5498 }
5499
5500 goto CompleteRequest;
5501 */
5502 status = SRB_STATUS_SUCCESS;
5503 goto CompleteRequest;
5504
5505 }
5506 } else {
5507 if (atapiDev) {
5508 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
5509 GetStatus(chan, statusByte);
5510 if(!(statusByte & IDE_STATUS_BUSY)) {
5511 // Assume command is completed if BUSY is cleared
5512 // even if NOT all data read
5513 // Optionally, we may receive COMPLETE interrupt later and
5514 // treat it as unexpected
5515 KdPrint2((PRINT_PREFIX "AtapiInterrupt: early complete + underrun ? status %x\n", statusByte));
5516
5517 status = SRB_STATUS_SUCCESS;
5518 goto CompleteRequest;
5519 }
5520 }
5521 }
5522
5523 goto ReturnEnableIntr;
5524
5525 } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) {
5526
5527 KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n"));
5528 // Command complete.
5529 if(DmaTransfer) {
5530 KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, was DmaTransfer\n"));
5531 AtaReq->WordsTransfered = AtaReq->WordsLeft;
5532 AtaReq->WordsLeft = 0;
5533 }
5534 //if (AtaReq->WordsLeft) {
5535 // status = SRB_STATUS_DATA_OVERRUN;
5536 //} else {
5537 status = SRB_STATUS_SUCCESS;
5538 //}
5539
5540 #ifdef UNIATA_DUMP_ATAPI
5541 if(srb &&
5542 srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5543 UCHAR ScsiCommand;
5544 PCDB Cdb;
5545 PCHAR CdbData;
5546 PCHAR ModeSelectData;
5547 ULONG CdbDataLen;
5548 PSCSI_REQUEST_BLOCK Srb = srb;
5549
5550 Cdb = (PCDB)(Srb->Cdb);
5551 ScsiCommand = Cdb->CDB6.OperationCode;
5552 CdbData = (PCHAR)(Srb->DataBuffer);
5553 CdbDataLen = Srb->DataTransferLength;
5554
5555 if(CdbDataLen > 0x1000) {
5556 CdbDataLen = 0x1000;
5557 }
5558
5559 KdPrint(("--\n"));
5560 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
5561 KdPrint2(("P:T:D=%d:%d:%d\n",
5562 Srb->PathId,
5563 Srb->TargetId,
5564 Srb->Lun));
5565 KdPrint(("Complete SCSI Command %2.2x\n", ScsiCommand));
5566 KdDump(Cdb, 16);
5567
5568 if(ScsiCommand == SCSIOP_MODE_SENSE) {
5569 KdPrint(("ModeSense 6\n"));
5570 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
5571 ModeSelectData = CdbData+4;
5572 KdDump(CdbData, CdbDataLen);
5573 } else
5574 if(ScsiCommand == SCSIOP_MODE_SENSE10) {
5575 KdPrint(("ModeSense 10\n"));
5576 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
5577 ModeSelectData = CdbData+8;
5578 KdDump(CdbData, CdbDataLen);
5579 } else {
5580 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5581 KdPrint(("Read buffer from device:\n"));
5582 KdDump(CdbData, CdbDataLen);
5583 }
5584 }
5585 KdPrint(("--\n"));
5586 }
5587 #endif //UNIATA_DUMP_ATAPI
5588
5589 CompleteRequest:
5590
5591 KdPrint2((PRINT_PREFIX "AtapiInterrupt: CompleteRequest, srbstatus %x\n", status));
5592 // Check and see if we are processing our secret (mechanism status/request sense) srb
5593
5594 if(AtaReq->WordsLeft && (status == SRB_STATUS_SUCCESS)) {
5595 KdPrint2((PRINT_PREFIX "WordsLeft %#x -> SRB_STATUS_DATA_OVERRUN\n", AtaReq->WordsLeft));
5596 status = SRB_STATUS_DATA_OVERRUN;
5597 }
5598
5599 if (AtaReq->OriginalSrb) {
5600
5601 ULONG srbStatus;
5602
5603 KdPrint2((PRINT_PREFIX "AtapiInterrupt: OriginalSrb != NULL\n"));
5604 if (srb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
5605
5606 KdPrint3((PRINT_PREFIX "AtapiInterrupt: SCSIOP_MECHANISM_STATUS status %#x\n", status));
5607 if (status == SRB_STATUS_SUCCESS) {
5608 // Bingo!!
5609 AtapiHwInitializeChanger (HwDeviceExtension,
5610 srb,
5611 (PMECHANICAL_STATUS_INFORMATION_HEADER) srb->DataBuffer);
5612
5613 // Get ready to issue the original srb
5614 srb = AtaReq->Srb = AtaReq->OriginalSrb;
5615 AtaReq->OriginalSrb = NULL;
5616
5617 } else {
5618 // failed! Get the sense key and maybe try again
5619 srb = AtaReq->Srb = BuildRequestSenseSrb (
5620 HwDeviceExtension,
5621 AtaReq->OriginalSrb);
5622 }
5623 /*
5624 // do not enable interrupts in DPC, do not waste time, do it now!
5625 if(UseDpc && chan->DisableIntr) {
5626 AtapiEnableInterrupts(HwDeviceExtension, c);
5627 UseDpc = FALSE;
5628 RestoreUseDpc = TRUE;
5629 }
5630 */
5631 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
5632
5633 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
5634
5635 if (srbStatus == SRB_STATUS_PENDING) {
5636 KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (1)\n"));
5637 goto ReturnEnableIntr;
5638 }
5639 /*
5640 if(RestoreUseDpc) {
5641 // restore state on error
5642 UseDpc = TRUE;
5643 AtapiDisableInterrupts(HwDeviceExtension, c);
5644 }
5645 */
5646
5647 } else { // srb->Cdb[0] == SCSIOP_REQUEST_SENSE)
5648
5649 PSENSE_DATA senseData = (PSENSE_DATA) srb->DataBuffer;
5650
5651 KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI command status %#x\n", status));
5652 if (status == SRB_STATUS_DATA_OVERRUN) {
5653 // Check to see if we at least get mininum number of bytes
5654 if ((srb->DataTransferLength - AtaReq->WordsLeft) >
5655 (FIELD_OFFSET (SENSE_DATA, AdditionalSenseLength) + sizeof(senseData->AdditionalSenseLength))) {
5656 status = SRB_STATUS_SUCCESS;
5657 }
5658 }
5659
5660 if (status == SRB_STATUS_SUCCESS) {
5661 #ifndef UNIATA_CORE
5662 if ((senseData->SenseKey != SCSI_SENSE_ILLEGAL_REQUEST) &&
5663 chan->MechStatusRetryCount) {
5664
5665 KdPrint3((PRINT_PREFIX "AtapiInterrupt: MechStatusRetryCount %#x\n", chan->MechStatusRetryCount));
5666 // The sense key doesn't say the last request is illegal, so try again
5667 chan->MechStatusRetryCount--;
5668 srb = AtaReq->Srb = BuildMechanismStatusSrb (
5669 HwDeviceExtension,
5670 AtaReq->OriginalSrb);
5671 } else {
5672
5673 // last request was illegal. No point trying again.
5674 // Do-nothing call ?
5675 AtapiHwInitializeChanger (HwDeviceExtension,
5676 srb,
5677 (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
5678
5679 // Get ready to issue the original srb
5680 srb = AtaReq->Srb = AtaReq->OriginalSrb;
5681 AtaReq->OriginalSrb = NULL;
5682 }
5683 #endif //UNIATA_CORE
5684 /*
5685 // do not enable interrupts in DPC, do not waste time, do it now!
5686 if(UseDpc && chan->DisableIntr) {
5687 AtapiEnableInterrupts(HwDeviceExtension, c);
5688 UseDpc = FALSE;
5689 RestoreUseDpc = TRUE;
5690 }
5691 */
5692 srbStatus = AtapiSendCommand(HwDeviceExtension, srb, CMD_ACTION_ALL);
5693
5694 KdPrint3((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (2)\n", chan->ExpectingInterrupt));
5695
5696 if (srbStatus == SRB_STATUS_PENDING) {
5697 KdPrint2((PRINT_PREFIX "AtapiInterrupt: send orig SRB_STATUS_PENDING (2)\n"));
5698 goto ReturnEnableIntr;
5699 }
5700 /*
5701 if(RestoreUseDpc) {
5702 // restore state on error
5703 UseDpc = TRUE;
5704 AtapiDisableInterrupts(HwDeviceExtension, c);
5705 }
5706 */
5707 }
5708 }
5709
5710 // If we get here, it means AtapiSendCommand() has failed
5711 // Can't recover. Pretend the original srb has failed and complete it.
5712
5713 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. complete OriginalSrb\n"));
5714
5715 if (AtaReq->OriginalSrb) {
5716 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n"));
5717 // Do-nothing call ?
5718 AtapiHwInitializeChanger (HwDeviceExtension,
5719 srb,
5720 (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
5721 srb = AtaReq->Srb = AtaReq->OriginalSrb;
5722 AtaReq->OriginalSrb = NULL;
5723 }
5724
5725 KdPrint2((PRINT_PREFIX "AtapiInterrupt: chan->ExpectingInterrupt %d (3)\n", chan->ExpectingInterrupt));
5726
5727 // fake an error and read no data
5728 status = SRB_STATUS_ERROR;
5729 srb->ScsiStatus = 0;
5730 AtaReq->DataBuffer = (PUSHORT)(srb->DataBuffer);
5731 AtaReq->WordsLeft = srb->DataTransferLength;
5732 chan->RDP = FALSE;
5733
5734 } else if (status == SRB_STATUS_ERROR) {
5735
5736 // Map error to specific SRB status and handle request sense.
5737 KdPrint3((PRINT_PREFIX "AtapiInterrupt: Error. Begin mapping...\n"));
5738 status = MapError(deviceExtension,
5739 srb);
5740
5741 chan->RDP = FALSE;
5742
5743 } else if(!DmaTransfer) {
5744
5745 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion\n"));
5746 // Command complete.
5747 PIO_wait_busy:
5748 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO completion, wait BUSY\n"));
5749 // Wait for busy to drop.
5750 for (i = 0; i < 5*30; i++) {
5751 GetBaseStatus(chan, statusByte);
5752 if (!(statusByte & IDE_STATUS_BUSY)) {
5753 break;
5754 }
5755 if(!InDpc) {
5756 // goto DPC
5757 AtaReq->ReqState = REQ_STATE_DPC_WAIT_BUSY;
5758 TimerValue = 200;
5759 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (busy)\n"));
5760 #ifndef UNIATA_CORE
5761 goto PostToDpc;
5762 #else //UNIATA_CORE
5763 AtapiStallExecution(TimerValue);
5764 goto ServiceInterrupt;
5765 #endif //UNIATA_CORE
5766 }
5767 AtapiStallExecution(100);
5768 }
5769
5770 if (i == 5*30) {
5771
5772 // reset the controller.
5773 KdPrint2((PRINT_PREFIX
5774 "AtapiInterrupt: Resetting due to BSY still up - %#x.\n",
5775 statusByte));
5776 goto IntrPrepareResetController;
5777 }
5778 // Check to see if DRQ is still up.
5779 if(statusByte & IDE_STATUS_DRQ) {
5780 KdPrint2((PRINT_PREFIX "AtapiInterrupt: DRQ...\n"));
5781 if(srb) {
5782 if(srb->SrbFlags & SRB_FLAGS_DATA_IN) {
5783 KdPrint2((PRINT_PREFIX "srb %x data in\n", srb));
5784 } else {
5785 KdPrint2((PRINT_PREFIX "srb %x data out\n", srb));
5786 }
5787 } else {
5788 KdPrint2((PRINT_PREFIX "srb NULL\n"));
5789 }
5790 if(AtaReq) {
5791 KdPrint2((PRINT_PREFIX "AtaReq %x AtaReq->WordsLeft=%x\n", AtaReq, AtaReq->WordsLeft));
5792 } else {
5793 KdPrint2((PRINT_PREFIX "AtaReq NULL\n"));
5794 }
5795 if(AtaReq && AtaReq->WordsLeft /*&&
5796 !(LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED))*/) {
5797 KdPrint2((PRINT_PREFIX "DRQ+AtaReq->WordsLeft -> next portion\n"));
5798 goto continue_PIO;
5799 }
5800 }
5801 //if (atapiDev && (statusByte & IDE_STATUS_DRQ)) {}
5802 //if ((statusByte & IDE_STATUS_DRQ)) {}
5803 if((statusByte & IDE_STATUS_DRQ) &&
5804 (LunExt->DeviceFlags & (DFLAGS_ATAPI_DEVICE | DFLAGS_TAPE_DEVICE | DFLAGS_LBA_ENABLED)) ) {
5805
5806 PIO_wait_DRQ:
5807 KdPrint2((PRINT_PREFIX "AtapiInterrupt: PIO_wait_DRQ\n"));
5808 for (i = 0; i < 200; i++) {
5809 GetBaseStatus(chan, statusByte);
5810 if (!(statusByte & IDE_STATUS_DRQ)) {
5811 break;
5812 }
5813 if(!InDpc) {
5814 // goto DPC
5815 KdPrint2((PRINT_PREFIX "AtapiInterrupt: go to DPC (drq)\n"));
5816 AtaReq->ReqState = REQ_STATE_DPC_WAIT_DRQ;
5817 TimerValue = 100;
5818 #ifndef UNIATA_CORE
5819 goto PostToDpc;
5820 #else //UNIATA_CORE
5821 AtapiStallExecution(TimerValue);
5822 goto ServiceInterrupt;
5823 #endif //UNIATA_CORE
5824 }
5825 AtapiStallExecution(100);
5826 }
5827
5828 if (i == 200) {
5829 // reset the controller.
5830 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Resetting due to DRQ still up - %#x\n",
5831 statusByte));
5832 goto IntrPrepareResetController;
5833 }
5834 }
5835 if(atapiDev) {
5836 KdPrint2(("IdeIntr: ATAPI Read AtaReq->DataBuffer %#x, srb->DataBuffer %#x, len %#x\n",
5837 AtaReq->DataBuffer, (srb ? srb->DataBuffer : (void*)(-1)), srb->DataTransferLength ));
5838 //KdDump(srb->DataBuffer, srb->DataTransferLength);
5839 }
5840 if(!AtapiDmaPioSync(HwDeviceExtension, srb, (PUCHAR)(srb->DataBuffer), srb->DataTransferLength)) {
5841 KdPrint2(("IdeIntr: Can't sync DMA and PIO buffers\n"));
5842 }
5843 }
5844
5845 // Clear interrupt expecting flag.
5846 UniataExpectChannelInterrupt(chan, FALSE);
5847 // clear this flag now, it can be set again in sub-calls
5848 InterlockedExchange(&(chan->CheckIntr),
5849 CHECK_INTR_IDLE);
5850
5851 // Sanity check that there is a current request.
5852 if(srb != NULL) {
5853 // Set status in SRB.
5854 srb->SrbStatus = (UCHAR)status;
5855
5856 // Check for underflow.
5857 if(AtaReq->WordsLeft) {
5858
5859 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Check for underflow, AtaReq->WordsLeft %x\n", AtaReq->WordsLeft));
5860 // Subtract out residual words and update if filemark hit,
5861 // setmark hit , end of data, end of media...
5862 if (!(LunExt->DeviceFlags & DFLAGS_TAPE_DEVICE)) {
5863 if (status == SRB_STATUS_DATA_OVERRUN) {
5864 srb->DataTransferLength -= AtaReq->WordsLeft*2;
5865 } else {
5866 srb->DataTransferLength = 0;
5867 }
5868 } else {
5869 srb->DataTransferLength -= AtaReq->WordsLeft*2;
5870 }
5871 }
5872 if(status == SRB_STATUS_SUCCESS) {
5873 //if(!(deviceExtension->HwFlags & UNIATA_AHCI) && !atapiDev) {
5874 // // This should be set in UniataAhciEndTransaction() for AHCI
5875 // AtaReq->WordsTransfered += AtaReq->bcount * DEV_BSIZE/2;
5876 //}
5877 if(!atapiDev &&
5878 AtaReq->WordsTransfered*2 < AtaReq->TransferLength) {
5879 KdPrint2((PRINT_PREFIX "AtapiInterrupt: more I/O required (%x of %x bytes) -> reenqueue\n",
5880 AtaReq->WordsTransfered*2, AtaReq->TransferLength));
5881 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
5882 AtaReq->ReqState = REQ_STATE_PREPARE_TO_NEXT;
5883 goto reenqueue_req;
5884 } else {
5885 KdPrint2((PRINT_PREFIX " Transfered %x, full size %x\n",
5886 AtaReq->WordsTransfered*2, AtaReq->TransferLength));
5887 }
5888 }
5889
5890 if (srb->Function != SRB_FUNCTION_IO_CONTROL) {
5891
5892 CompleteRDP:
5893 // Indicate command complete.
5894 if (!(chan->RDP)) {
5895 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete\n"));
5896 IntrCompleteReq:
5897
5898 if (status == SRB_STATUS_SUCCESS &&
5899 srb->SenseInfoBuffer &&
5900 srb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
5901
5902 PSENSE_DATA senseBuffer = (PSENSE_DATA)srb->SenseInfoBuffer;
5903
5904 KdPrint2((PRINT_PREFIX "AtapiInterrupt: set AutoSense\n"));
5905 senseBuffer->ErrorCode = 0;
5906 senseBuffer->Valid = 1;
5907 senseBuffer->AdditionalSenseLength = 0xb;
5908 senseBuffer->SenseKey = 0;
5909 senseBuffer->AdditionalSenseCode = 0;
5910 senseBuffer->AdditionalSenseCodeQualifier = 0;
5911
5912 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
5913 }
5914 AtapiDmaDBSync(chan, srb);
5915 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove srb %#x, status %x\n", srb, status));
5916 UniataRemoveRequest(chan, srb);
5917 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestComplete, srb %#x\n", srb));
5918 ScsiPortNotification(RequestComplete,
5919 deviceExtension,
5920 srb);
5921 }
5922 } else {
5923
5924 KdPrint2((PRINT_PREFIX "AtapiInterrupt: IOCTL completion\n"));
5925
5926 if (status != SRB_STATUS_SUCCESS) {
5927 error = AtapiReadPort1(chan, IDX_IO1_i_Error);
5928 KdPrint2((PRINT_PREFIX "AtapiInterrupt: error %#x\n", error));
5929 }
5930
5931 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
5932
5933 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
5934 // Build the SMART status block depending upon the completion status.
5935 cmdOutParameters->cBufferSize = wordCount;
5936 cmdOutParameters->DriverStatus.bDriverError = (error) ? SMART_IDE_ERROR : 0;
5937 cmdOutParameters->DriverStatus.bIDEError = error;
5938
5939 // If the sub-command is return smart status, jam the value from cylinder low and high, into the
5940 // data buffer.
5941 if (chan->SmartCommand == RETURN_SMART_STATUS) {
5942 PIDEREGS_EX regs = (PIDEREGS_EX)&(cmdOutParameters->bBuffer);
5943
5944 regs->bOpFlags = 0;
5945 UniataSnapAtaRegs(chan, 0, regs);
5946
5947 regs->bCommandReg = SMART_CMD;
5948 regs->bFeaturesReg = RETURN_SMART_STATUS;
5949
5950 cmdOutParameters->cBufferSize = 8;
5951 }
5952 chan->SmartCommand = 0; // cleanup after execution
5953 }
5954 // Indicate command complete.
5955 goto IntrCompleteReq;
5956 }
5957
5958 } else {
5959
5960 KdPrint2((PRINT_PREFIX "AtapiInterrupt: No SRB!\n"));
5961 }
5962
5963 if (chan->RDP) {
5964 // Check DSC
5965 for (i = 0; i < 5; i++) {
5966 GetBaseStatus(chan, statusByte);
5967 if(!(statusByte & IDE_STATUS_BUSY)) {
5968 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RDP + cleared BUSY\n"));
5969 chan->RDP = FALSE;
5970 goto CompleteRDP;
5971 } else
5972 if (statusByte & IDE_STATUS_DSC) {
5973 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Clear RDP\n"));
5974 chan->RDP = FALSE;
5975 goto CompleteRDP;
5976 }
5977 AtapiStallExecution(50);
5978 }
5979 }
5980 // RDP can be cleared since previous check
5981 if (chan->RDP) {
5982 KdPrint2((PRINT_PREFIX "AtapiInterrupt: RequestTimerCall 2000\n"));
5983
5984 TimerValue = 2000;
5985 #ifndef UNIATA_CORE
5986 goto CallTimerDpc;
5987 #else //UNIATA_CORE
5988 AtapiStallExecution(TimerValue);
5989 goto ServiceInterrupt;
5990 #endif //UNIATA_CORE
5991 }
5992
5993 // ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
5994 enqueue_next_req:
5995 // Get next request
5996 srb = UniataGetCurRequest(chan);
5997
5998 reenqueue_req:
5999
6000 #ifndef UNIATA_CORE
6001 KdPrint2((PRINT_PREFIX "AtapiInterrupt: NextRequest, srb=%#x\n",srb));
6002 if(!srb) {
6003 ScsiPortNotification(NextRequest,
6004 deviceExtension,
6005 NULL);
6006 } else {
6007 ScsiPortNotification(NextLuRequest,
6008 deviceExtension,
6009 PathId,
6010 TargetId,
6011 Lun);
6012 // in simplex mode next command must NOT be sent here
6013 if(!deviceExtension->simplexOnly) {
6014 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
6015 }
6016 }
6017 // Try to get SRB fron any non-empty queue (later)
6018 if(deviceExtension->simplexOnly) {
6019 NoStartIo = FALSE;
6020 }
6021 #endif //UNIATA_CORE
6022
6023 goto ReturnEnableIntr;
6024
6025 } else {
6026
6027 // Unexpected int. Catch it
6028 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Unexpected ATAPI interrupt. InterruptReason %#x. Status %#x.\n",
6029 interruptReason,
6030 statusByte));
6031
6032 if(OldReqState == REQ_STATE_DPC_WAIT_BUSY0 &&
6033 AtaReq->WordsLeft == 0) {
6034 KdPrint2((PRINT_PREFIX "AtapiInterrupt: pending WAIT_BUSY0. Complete.\n"));
6035 status = SRB_STATUS_SUCCESS;
6036 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
6037 goto CompleteRequest;
6038 }
6039 }
6040
6041 ReturnEnableIntr:
6042
6043 KdPrint2((PRINT_PREFIX "AtapiInterrupt: ReturnEnableIntr\n",srb));
6044 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6045 deviceExtension->ExpectingInterrupt = TRUE;
6046 if(UseDpc) {
6047 if(CrNtInterlockedExchangeAdd(&(chan->DisableIntr), 0)) {
6048 KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiEnableInterrupts__()\n"));
6049 #ifdef UNIATA_USE_XXableInterrupts
6050 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
6051 chan->ChannelCtrlFlags |= CTRFLAGS_ENABLE_INTR_REQ;
6052 // must be called on DISPATCH_LEVEL
6053 ScsiPortNotification(CallDisableInterrupts, HwDeviceExtension,
6054 AtapiEnableInterrupts__);
6055 #else
6056 AtapiEnableInterrupts(HwDeviceExtension, c);
6057 InterlockedExchange(&(chan->CheckIntr),
6058 CHECK_INTR_IDLE);
6059 // Will raise IRQL to DIRQL
6060 #ifndef UNIATA_CORE
6061 AtapiQueueTimerDpc(HwDeviceExtension, lChannel,
6062 AtapiEnableInterrupts__,
6063 1);
6064 #endif // UNIATA_CORE
6065 KdPrint2((PRINT_PREFIX "AtapiInterrupt: Timer DPC inited\n"));
6066 #endif // UNIATA_USE_XXableInterrupts
6067 }
6068 }
6069
6070 InterlockedExchange(&(chan->CheckIntr), CHECK_INTR_IDLE);
6071 // in simplex mode next command must be sent here if
6072 // DPC is not used
6073 KdPrint2((PRINT_PREFIX "AtapiInterrupt: exiting, UseDpc=%d, NoStartIo=%d\n", UseDpc, NoStartIo));
6074
6075 #ifndef UNIATA_CORE
6076 if(!UseDpc && /*deviceExtension->simplexOnly &&*/ !NoStartIo) {
6077 chan = UniataGetNextChannel(chan);
6078 if(chan) {
6079 srb = UniataGetCurRequest(chan);
6080 } else {
6081 srb = NULL;
6082 }
6083 KdPrint2((PRINT_PREFIX "AtapiInterrupt: run srb %x\n", srb));
6084 if(srb) {
6085 AtapiStartIo__(HwDeviceExtension, srb, FALSE);
6086 }
6087 }
6088 #endif //UNIATA_CORE
6089 return TRUE;
6090
6091 } // end AtapiInterrupt__()
6092
6093 #ifndef UNIATA_CORE
6094
6095 /*++
6096
6097 Routine Description:
6098
6099 This routine handles SMART enable, disable, read attributes and threshold commands.
6100
6101 Arguments:
6102
6103 HwDeviceExtension - HBA miniport driver's adapter data storage
6104 Srb - IO request packet
6105
6106 Return Value:
6107
6108 SRB status
6109
6110 --*/
6111 ULONG
6112 NTAPI
6113 IdeSendSmartCommand(
6114 IN PVOID HwDeviceExtension,
6115 IN PSCSI_REQUEST_BLOCK Srb,
6116 IN ULONG targetId // assume it is always valid
6117 )
6118 {
6119 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6120 ULONG c ; // = GET_CHANNEL(Srb); may be invalid
6121 PHW_CHANNEL chan ; // = &(deviceExtension->chan[c]);
6122 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
6123 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6124 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
6125 PIDEREGS regs = &cmdInParameters.irDriveRegs;
6126 // ULONG i;
6127 UCHAR statusByte;
6128 ULONG DeviceNumber;
6129
6130 if (regs->bCommandReg != SMART_CMD) {
6131 KdPrint2((PRINT_PREFIX
6132 "IdeSendSmartCommand: bCommandReg != SMART_CMD\n"));
6133 return SRB_STATUS_INVALID_REQUEST;
6134 }
6135
6136 c = targetId / deviceExtension->NumberLuns;
6137 DeviceNumber = targetId % deviceExtension->NumberLuns;
6138 KdPrint2((PRINT_PREFIX " c %d, dev %d\n", c, DeviceNumber));
6139
6140 chan = &(deviceExtension->chan[c]);
6141
6142 chan->SmartCommand = regs->bFeaturesReg;
6143
6144 // Determine which of the commands to carry out.
6145 switch(regs->bFeaturesReg) {
6146 case READ_ATTRIBUTES:
6147 case READ_THRESHOLDS:
6148 case READ_LOG_SECTOR:
6149 case WRITE_LOG_SECTOR:
6150
6151 if(Srb->DataTransferLength < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1) {
6152 KdPrint2((PRINT_PREFIX
6153 "IdeSendSmartCommand: wrong buffer size\n"));
6154 return SRB_STATUS_DATA_OVERRUN;
6155 }
6156
6157 statusByte = WaitOnBusy(chan);
6158
6159 if (statusByte & IDE_STATUS_BUSY) {
6160 KdPrint2((PRINT_PREFIX
6161 "IdeSendSmartCommand: Returning BUSY status\n"));
6162 return SRB_STATUS_BUSY;
6163 }
6164
6165 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6166 RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) + READ_ATTRIBUTE_BUFFER_SIZE - 1);
6167
6168 // Set data buffer pointer and words left.
6169 AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
6170 AtaReq->WordsLeft = READ_ATTRIBUTE_BUFFER_SIZE / 2;
6171
6172 statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
6173 regs->bCommandReg,
6174 (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
6175 0,
6176 regs->bSectorNumberReg,
6177 regs->bSectorCountReg,
6178 regs->bFeaturesReg,
6179 ATA_IMMEDIATE);
6180
6181 if(!(statusByte & IDE_STATUS_ERROR)) {
6182 // Wait for interrupt.
6183 return SRB_STATUS_PENDING;
6184 }
6185 return SRB_STATUS_ERROR;
6186
6187 case ENABLE_SMART:
6188 case DISABLE_SMART:
6189 case RETURN_SMART_STATUS:
6190 case ENABLE_DISABLE_AUTOSAVE:
6191 case EXECUTE_OFFLINE_DIAGS:
6192 case SAVE_ATTRIBUTE_VALUES:
6193 case AUTO_OFFLINE:
6194
6195 statusByte = WaitOnBusy(chan);
6196
6197 if (statusByte & IDE_STATUS_BUSY) {
6198 KdPrint2((PRINT_PREFIX
6199 "IdeSendSmartCommand: Returning BUSY status\n"));
6200 return SRB_STATUS_BUSY;
6201 }
6202
6203 // Zero the ouput buffer as the input buffer info. has been saved off locally (the buffers are the same).
6204 RtlZeroMemory(cmdOutParameters, sizeof(SENDCMDOUTPARAMS) - 1);
6205
6206 // Set data buffer pointer and indicate no data transfer.
6207 AtaReq->DataBuffer = (PUSHORT)cmdOutParameters->bBuffer;
6208 AtaReq->WordsLeft = 0;
6209
6210 statusByte = AtaCommand(deviceExtension, DeviceNumber, c,
6211 regs->bCommandReg,
6212 (USHORT)(regs->bCylLowReg) | (((USHORT)(regs->bCylHighReg)) << 8),
6213 0,
6214 regs->bSectorNumberReg,
6215 regs->bSectorCountReg,
6216 regs->bFeaturesReg,
6217 ATA_IMMEDIATE);
6218
6219 if(!(statusByte & IDE_STATUS_ERROR)) {
6220 // Wait for interrupt.
6221 UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6222 return SRB_STATUS_PENDING;
6223 }
6224 return SRB_STATUS_ERROR;
6225 } // end switch(regs->bFeaturesReg)
6226
6227 return SRB_STATUS_INVALID_REQUEST;
6228
6229 } // end IdeSendSmartCommand()
6230
6231 #endif //UNIATA_CORE
6232
6233 ULONGLONG
6234 NTAPI
6235 UniAtaCalculateLBARegs(
6236 PHW_LU_EXTENSION LunExt,
6237 ULONGLONG startingSector,
6238 PULONG max_bcount
6239 )
6240 {
6241 UCHAR drvSelect,sectorNumber;
6242 USHORT cylinder;
6243 ULONG tmp;
6244
6245 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
6246 if(LunExt->LimitedTransferMode >= ATA_DMA) {
6247 if(LunExt->DeviceExtension) {
6248 (*max_bcount) = LunExt->DeviceExtension->MaximumDmaTransferLength / DEV_BSIZE;
6249 }
6250 }
6251 return startingSector;
6252 }
6253 tmp = LunExt->IdentifyData.SectorsPerTrack *
6254 LunExt->IdentifyData.NumberOfHeads;
6255 if(!tmp) {
6256 KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: 0-sized\n"));
6257 cylinder = 0;
6258 drvSelect = 0;
6259 sectorNumber = 1;
6260 (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack;
6261 } else {
6262 cylinder = (USHORT)(startingSector / tmp);
6263 drvSelect = (UCHAR)((startingSector % tmp) / LunExt->IdentifyData.SectorsPerTrack);
6264 sectorNumber = (UCHAR)(startingSector % LunExt->IdentifyData.SectorsPerTrack) + 1;
6265 (*max_bcount) = LunExt->IdentifyData.SectorsPerTrack - sectorNumber + 1;
6266 KdPrint2((PRINT_PREFIX "UniAtaCalculateLBARegs: C:H:S=%#x:%#x:%#x, max_bc %#x\n",
6267 cylinder, drvSelect, sectorNumber, (*max_bcount)));
6268 }
6269 (*max_bcount) = 0;
6270
6271 return (ULONG)(sectorNumber&0xff) | (((ULONG)cylinder&0xffff)<<8) | (((ULONG)drvSelect&0xf)<<24);
6272 } // end UniAtaCalculateLBARegs()
6273
6274 ULONGLONG
6275 NTAPI
6276 UniAtaCalculateLBARegsBack(
6277 PHW_LU_EXTENSION LunExt,
6278 ULONGLONG lba
6279 )
6280 {
6281 ULONG drvSelect,sectorNumber;
6282 ULONG cylinder;
6283 ULONG tmp;
6284
6285 if(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
6286 return lba;
6287 }
6288 tmp = LunExt->IdentifyData.SectorsPerTrack *
6289 LunExt->IdentifyData.NumberOfHeads;
6290
6291 cylinder = (USHORT)((lba >> 8) & 0xffff);
6292 drvSelect = (UCHAR)((lba >> 24) & 0xf);
6293 sectorNumber = (UCHAR)(lba & 0xff);
6294
6295 lba = sectorNumber-1 +
6296 (drvSelect*LunExt->IdentifyData.SectorsPerTrack) +
6297 (cylinder*tmp);
6298
6299 return lba;
6300 } // end UniAtaCalculateLBARegsBack()
6301
6302
6303 /*++
6304
6305 Routine Description:
6306
6307 This routine handles IDE read and writes.
6308
6309 Arguments:
6310
6311 HwDeviceExtension - HBA miniport driver's adapter data storage
6312 Srb - IO request packet
6313
6314 Return Value:
6315
6316 SRB status
6317
6318 --*/
6319 ULONG
6320 NTAPI
6321 IdeReadWrite(
6322 IN PVOID HwDeviceExtension,
6323 IN PSCSI_REQUEST_BLOCK Srb,
6324 IN ULONG CmdAction
6325 )
6326 {
6327 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6328 UCHAR lChannel = GET_CHANNEL(Srb);
6329 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
6330 PHW_LU_EXTENSION LunExt;
6331 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
6332 //ULONG ldev = GET_LDEV(Srb);
6333 UCHAR DeviceNumber = GET_CDEV(Srb);;
6334 ULONGLONG startingSector=0;
6335 ULONG max_bcount;
6336 ULONG wordCount = 0;
6337 UCHAR statusByte,statusByte2;
6338 UCHAR cmd;
6339 ULONGLONG lba;
6340 BOOLEAN use_dma = FALSE;
6341 ULONG fis_size;
6342
6343 AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
6344 LunExt = chan->lun[DeviceNumber];
6345
6346 if((CmdAction & CMD_ACTION_PREPARE) &&
6347 (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
6348
6349 if(LunExt->opt_ReadOnly &&
6350 (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) {
6351 if(LunExt->opt_ReadOnly == 1) {
6352 KdPrint2((PRINT_PREFIX "Abort WRITE (Soft R/O)\n"));
6353 return SRB_STATUS_ERROR;
6354 } else {
6355 KdPrint2((PRINT_PREFIX "Ignore WRITE (Soft R/O)\n"));
6356 return SRB_STATUS_SUCCESS;
6357 }
6358 }
6359
6360 // Set data buffer pointer and words left.
6361 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
6362
6363 if(AtaReq->WordsTransfered) {
6364 AtaReq->DataBuffer = ((PUSHORT)(Srb->DataBuffer)) + AtaReq->WordsTransfered;
6365 startingSector = (UniAtaCalculateLBARegsBack(LunExt, AtaReq->lba)) /* latest lba */ + AtaReq->bcount /* previous bcount */;
6366 AtaReq->bcount = (AtaReq->TransferLength - AtaReq->WordsTransfered*2 + DEV_BSIZE-1) / DEV_BSIZE;
6367 KdPrint2((PRINT_PREFIX "IdeReadWrite (Chained REQ): Starting sector %I64x, OrigWordsRequested %#x, WordsTransfered %#x, DevSize %#x\n",
6368 startingSector,
6369 AtaReq->TransferLength/2,
6370 AtaReq->WordsTransfered,
6371 AtaReq->bcount));
6372 } else {
6373 AtaReq->DataBuffer = (PUSHORT)(Srb->DataBuffer);
6374 AtaReq->TransferLength = Srb->DataTransferLength;
6375 // Set up 1st block.
6376 switch(Srb->Cdb[0]) {
6377 case SCSIOP_READ:
6378 case SCSIOP_WRITE:
6379 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
6380 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
6381 break;
6382 case SCSIOP_READ12:
6383 case SCSIOP_WRITE12:
6384 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA);
6385 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
6386 break;
6387 case SCSIOP_READ16:
6388 case SCSIOP_WRITE16:
6389 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
6390 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
6391 break;
6392 }
6393 KdPrint2((PRINT_PREFIX "IdeReadWrite (Orig REQ): Starting sector %I64x, OrigWordsRequested %#x, DevSize %#x\n",
6394 startingSector,
6395 AtaReq->TransferLength/2,
6396 AtaReq->bcount));
6397 }
6398 lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
6399
6400 if(max_bcount) {
6401 AtaReq->bcount = min(AtaReq->bcount, max_bcount);
6402 }
6403 AtaReq->WordsLeft = min(AtaReq->TransferLength - AtaReq->WordsTransfered*2,
6404 AtaReq->bcount * DEV_BSIZE) / 2;
6405
6406 KdPrint2((PRINT_PREFIX "IdeReadWrite (REQ): Starting sector is %I64x, Number of WORDS %#x, DevSize %#x\n",
6407 startingSector,
6408 AtaReq->WordsLeft,
6409 AtaReq->bcount));
6410
6411 AtaReq->lba = lba;
6412
6413 // assume best case here
6414 // we cannot reinit Dma until previous request is completed
6415 if(deviceExtension->HwFlags & UNIATA_AHCI) {
6416 UniataAhciSetupCmdPtr(AtaReq);
6417 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
6418 (PUCHAR)(AtaReq->DataBuffer),
6419 AtaReq->bcount * DEV_BSIZE)) {
6420 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !DMA\n"));
6421 return SRB_STATUS_ERROR;
6422 }
6423 } else
6424 if ((LunExt->LimitedTransferMode >= ATA_DMA)) {
6425 use_dma = TRUE;
6426 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
6427 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
6428 (PUCHAR)(AtaReq->DataBuffer),
6429 AtaReq->bcount * DEV_BSIZE)) {
6430 use_dma = FALSE;
6431 }
6432 }
6433
6434 if(deviceExtension->HwFlags & UNIATA_AHCI) {
6435 KdPrint2((PRINT_PREFIX "IdeReadWrite: setup AHCI FIS\n"));
6436 RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
6437
6438 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
6439 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
6440 (AtaReq->Flags & REQ_FLAG_READ) ? IDE_COMMAND_READ_DMA : IDE_COMMAND_WRITE_DMA,
6441 lba,
6442 (USHORT)(AtaReq->bcount),
6443 0
6444 /*,(AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE*/
6445 );
6446
6447 if(!fis_size) {
6448 KdPrint3((PRINT_PREFIX "IdeReadWrite: AHCI !FIS\n"));
6449 return SRB_STATUS_ERROR;
6450 }
6451
6452 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0, (AtaReq->Flags & REQ_FLAG_READ) ? 0 : ATA_AHCI_CMD_WRITE, fis_size, DeviceNumber);
6453 KdPrint2((PRINT_PREFIX "IdeReadWrite ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
6454 }
6455
6456 AtaReq->ReqState = REQ_STATE_READY_TO_TRANSFER;
6457
6458 } else { // exec_only
6459 KdPrint2((PRINT_PREFIX "IdeReadWrite (ExecOnly): \n"));
6460 lba = AtaReq->lba;
6461
6462 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
6463 use_dma = TRUE;
6464 }
6465 }
6466 if(!(CmdAction & CMD_ACTION_EXEC)) {
6467
6468 return SRB_STATUS_PENDING;
6469 }
6470
6471 // if this is queued request, reinit DMA and check
6472 // if DMA mode is still available
6473 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
6474 if (/*EnableDma &&*/
6475 (LunExt->TransferMode >= ATA_DMA)) {
6476 use_dma = TRUE;
6477 } else {
6478 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
6479 use_dma = FALSE;
6480 }
6481
6482 // Check if write request.
6483 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
6484
6485 // Prepare read command.
6486 if(use_dma) {
6487 cmd = IDE_COMMAND_READ_DMA;
6488 } else
6489 if(LunExt->MaximumBlockXfer) {
6490 cmd = IDE_COMMAND_READ_MULTIPLE;
6491 } else {
6492 cmd = IDE_COMMAND_READ;
6493 }
6494 } else {
6495
6496 // Prepare write command.
6497 if (use_dma) {
6498 wordCount = AtaReq->bcount*DEV_BSIZE/2;
6499 cmd = IDE_COMMAND_WRITE_DMA;
6500 } else
6501 if (LunExt->MaximumBlockXfer) {
6502 wordCount = DEV_BSIZE/2 * LunExt->MaximumBlockXfer;
6503
6504 if (AtaReq->WordsLeft < wordCount) {
6505 // Transfer only words requested.
6506 wordCount = AtaReq->WordsLeft;
6507 }
6508 cmd = IDE_COMMAND_WRITE_MULTIPLE;
6509
6510 } else {
6511 wordCount = DEV_BSIZE/2;
6512 cmd = IDE_COMMAND_WRITE;
6513 }
6514 }
6515
6516 // Send IO command.
6517 KdPrint2((PRINT_PREFIX "IdeReadWrite: Lba %#I64x, Count %#x(%#x)\n", lba, ((Srb->DataTransferLength + 0x1FF) / 0x200),
6518 ((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE)));
6519 if(use_dma) {
6520 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
6521 } else {
6522 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
6523 }
6524
6525 if(deviceExtension->HwFlags & UNIATA_AHCI) {
6526 // AHCI doesn't distinguish DMA and PIO
6527 //AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6528 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
6529 UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
6530 InterlockedExchange(&(chan->CheckIntr),
6531 CHECK_INTR_IDLE);
6532 return SRB_STATUS_PENDING;
6533 }
6534
6535 if ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ||
6536 use_dma) {
6537 statusByte2 = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
6538 cmd, lba,
6539 (USHORT)(AtaReq->bcount),
6540 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6541 0, ATA_IMMEDIATE);
6542 if(statusByte2 != IDE_STATUS_WRONG) {
6543 GetStatus(chan, statusByte2);
6544 }
6545 if(statusByte2 & IDE_STATUS_ERROR) {
6546 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
6547 KdPrint2((PRINT_PREFIX "IdeReadWrite: status %#x, error %#x\n", statusByte2, statusByte));
6548 return SRB_STATUS_ERROR;
6549 }
6550 if(use_dma) {
6551 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
6552 }
6553 return SRB_STATUS_PENDING;
6554 }
6555
6556 statusByte = AtaCommand48(deviceExtension, DeviceNumber, lChannel,
6557 cmd, lba,
6558 (USHORT)(AtaReq->bcount),
6559 // (UCHAR)((wordCount*2 + DEV_BSIZE-1) / DEV_BSIZE),
6560 0, ATA_WAIT_INTR);
6561
6562 if (!(statusByte & IDE_STATUS_DRQ) ||
6563 statusByte == IDE_STATUS_WRONG) {
6564
6565 if(statusByte == IDE_STATUS_WRONG) {
6566 KdPrint2((PRINT_PREFIX
6567 "IdeReadWrite: error sending command (%#x)\n",
6568 statusByte));
6569 } else {
6570 KdPrint2((PRINT_PREFIX
6571 "IdeReadWrite: DRQ never asserted (%#x)\n",
6572 statusByte));
6573 }
6574
6575 AtaReq->WordsLeft = 0;
6576
6577 // Clear interrupt expecting flag.
6578 UniataExpectChannelInterrupt(chan, FALSE);
6579 InterlockedExchange(&(chan->CheckIntr),
6580 CHECK_INTR_IDLE);
6581
6582 // Clear current SRB.
6583 UniataRemoveRequest(chan, Srb);
6584
6585 return (statusByte == IDE_STATUS_WRONG) ? SRB_STATUS_ERROR : SRB_STATUS_TIMEOUT;
6586 }
6587
6588 UniataExpectChannelInterrupt(chan, TRUE);
6589 InterlockedExchange(&(chan->CheckIntr),
6590 CHECK_INTR_IDLE);
6591
6592 // Write next DEV_BSIZE/2*N words.
6593 if (!(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED)) {
6594 KdPrint2((PRINT_PREFIX
6595 "IdeReadWrite: Write %#x words\n", wordCount));
6596
6597 WriteBuffer(chan,
6598 AtaReq->DataBuffer,
6599 wordCount,
6600 UniataGetPioTiming(LunExt));
6601
6602 } else {
6603
6604 KdPrint2((PRINT_PREFIX
6605 "IdeReadWrite: Write %#x Dwords\n", wordCount/2));
6606
6607 WriteBuffer2(chan,
6608 (PULONG)(AtaReq->DataBuffer),
6609 wordCount / 2,
6610 UniataGetPioTiming(LunExt));
6611 }
6612
6613 // Adjust buffer address and words left count.
6614 AtaReq->WordsLeft -= wordCount;
6615 AtaReq->DataBuffer += wordCount;
6616
6617 // Wait for interrupt.
6618 return SRB_STATUS_PENDING;
6619
6620 } // end IdeReadWrite()
6621
6622 #ifndef UNIATA_CORE
6623
6624 /*++
6625
6626 Routine Description:
6627 This routine handles IDE Verify.
6628
6629 Arguments:
6630 HwDeviceExtension - HBA miniport driver's adapter data storage
6631 Srb - IO request packet
6632 `
6633 Return Value:
6634 SRB status
6635
6636 --*/
6637 ULONG
6638 NTAPI
6639 IdeVerify(
6640 IN PVOID HwDeviceExtension,
6641 IN PSCSI_REQUEST_BLOCK Srb
6642 )
6643 {
6644 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6645 UCHAR lChannel = GET_CHANNEL(Srb);
6646 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
6647 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
6648 PHW_LU_EXTENSION LunExt;
6649 //ULONG ldev = GET_LDEV(Srb);
6650 ULONG DeviceNumber = GET_CDEV(Srb);
6651 UCHAR statusByte;
6652 ULONGLONG startingSector=0;
6653 ULONG max_bcount;
6654 ULONGLONG sectors;
6655 ULONGLONG endSector;
6656 ULONG sectorCount=0;
6657 ULONGLONG lba;
6658
6659 LunExt = chan->lun[DeviceNumber];
6660 // Drive has these number sectors.
6661 if(!(sectors = (ULONG)(LunExt->NumOfSectors))) {
6662 sectors = LunExt->IdentifyData.SectorsPerTrack *
6663 LunExt->IdentifyData.NumberOfHeads *
6664 LunExt->IdentifyData.NumberOfCylinders;
6665 }
6666
6667 KdPrint2((PRINT_PREFIX
6668 "IdeVerify: Total sectors %#x\n",
6669 sectors));
6670
6671 // Get starting sector number from CDB.
6672 switch(Srb->Cdb[0]) {
6673 case SCSIOP_VERIFY:
6674 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB10.LBA);
6675 MOV_SWP_DW2DD(sectorCount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
6676 break;
6677 case SCSIOP_VERIFY12:
6678 MOV_DD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB12READWRITE.LBA);
6679 MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
6680 break;
6681 case SCSIOP_VERIFY16:
6682 MOV_QD_SWP(startingSector, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
6683 MOV_DD_SWP(sectorCount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
6684 break;
6685 }
6686
6687 KdPrint2((PRINT_PREFIX
6688 "IdeVerify: Starting sector %#I64x. Number of blocks %#x\n",
6689 startingSector,
6690 sectorCount));
6691
6692 endSector = startingSector + sectorCount;
6693
6694 KdPrint2((PRINT_PREFIX
6695 "IdeVerify: Ending sector %#I64x\n",
6696 endSector));
6697
6698 if (endSector > sectors) {
6699
6700 // Too big, round down.
6701 KdPrint2((PRINT_PREFIX
6702 "IdeVerify: Truncating request to %#x blocks\n",
6703 sectors - startingSector - 1));
6704
6705 sectorCount = (ULONG)(sectors - startingSector - 1);
6706
6707 } else {
6708
6709 // Set up sector count register. Round up to next block.
6710 if (sectorCount > 0xFF) {
6711 sectorCount = (USHORT)0xFF;
6712 }
6713 }
6714
6715 // Set data buffer pointer and words left.
6716 AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
6717 AtaReq->WordsLeft = Srb->DataTransferLength / 2;
6718
6719 // Indicate expecting an interrupt.
6720 InterlockedExchange(&(chan->CheckIntr),
6721 CHECK_INTR_IDLE);
6722
6723 lba = UniAtaCalculateLBARegs(LunExt, startingSector, &max_bcount);
6724
6725 statusByte = AtaCommand48(deviceExtension, LunExt->Lun, GET_CHANNEL(Srb),
6726 IDE_COMMAND_VERIFY, lba,
6727 (USHORT)sectorCount,
6728 0, ATA_IMMEDIATE);
6729
6730 if(!(statusByte & IDE_STATUS_ERROR)) {
6731 // Wait for interrupt.
6732 return SRB_STATUS_PENDING;
6733 }
6734 return SRB_STATUS_ERROR;
6735
6736 } // end IdeVerify()
6737
6738 #endif //UNIATA_CORE
6739
6740 /*++
6741
6742 Routine Description:
6743 Send ATAPI packet command to device.
6744
6745 Arguments:
6746 HwDeviceExtension - HBA miniport driver's adapter data storage
6747 Srb - IO request packet
6748
6749 Return Value:
6750
6751 --*/
6752 ULONG
6753 NTAPI
6754 AtapiSendCommand(
6755 IN PVOID HwDeviceExtension,
6756 IN PSCSI_REQUEST_BLOCK Srb,
6757 IN ULONG CmdAction
6758 )
6759 {
6760 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
6761 UCHAR lChannel = GET_CHANNEL(Srb);
6762 PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
6763 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
6764 PHW_LU_EXTENSION LunExt;
6765 //ULONG ldev = GET_LDEV(Srb);
6766 ULONG DeviceNumber = GET_CDEV(Srb);
6767 ULONG flags;
6768 UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh;
6769 BOOLEAN use_dma = FALSE;
6770 BOOLEAN dma_reinited = FALSE;
6771 BOOLEAN retried = FALSE;
6772 ULONG fis_size;
6773 UCHAR FeatureReg=0;
6774
6775 LunExt = chan->lun[DeviceNumber];
6776
6777 KdPrint3((PRINT_PREFIX "AtapiSendCommand: req state %#x, Action %x\n", AtaReq->ReqState, CmdAction));
6778 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
6779 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
6780
6781
6782 #ifdef UNIATA_DUMP_ATAPI
6783 if(CmdAction & CMD_ACTION_PREPARE) {
6784 UCHAR ScsiCommand;
6785 PCDB Cdb;
6786 PCHAR CdbData;
6787 PCHAR ModeSelectData;
6788 ULONG CdbDataLen;
6789
6790 Cdb = (PCDB)(Srb->Cdb);
6791 ScsiCommand = Cdb->CDB6.OperationCode;
6792 CdbData = (PCHAR)(Srb->DataBuffer);
6793 CdbDataLen = Srb->DataTransferLength;
6794
6795 if(CdbDataLen > 0x1000) {
6796 CdbDataLen = 0x1000;
6797 }
6798
6799 KdPrint(("--\n"));
6800 KdPrint2(("VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
6801 KdPrint2(("P:T:D=%d:%d:%d\n",
6802 Srb->PathId,
6803 Srb->TargetId,
6804 Srb->Lun));
6805 KdPrint(("SCSI Command %2.2x\n", ScsiCommand));
6806 KdDump(Cdb, 16);
6807
6808 if(ScsiCommand == SCSIOP_WRITE_CD) {
6809 KdPrint(("Write10, LBA %2.2x%2.2x%2.2x%2.2x\n",
6810 Cdb->WRITE_CD.LBA[0],
6811 Cdb->WRITE_CD.LBA[1],
6812 Cdb->WRITE_CD.LBA[2],
6813 Cdb->WRITE_CD.LBA[3]
6814 ));
6815 } else
6816 if(ScsiCommand == SCSIOP_WRITE12) {
6817 KdPrint(("Write12, LBA %2.2x%2.2x%2.2x%2.2x\n",
6818 Cdb->CDB12READWRITE.LBA[0],
6819 Cdb->CDB12READWRITE.LBA[1],
6820 Cdb->CDB12READWRITE.LBA[2],
6821 Cdb->CDB12READWRITE.LBA[3]
6822 ));
6823 } else
6824 if(ScsiCommand == SCSIOP_WRITE16) {
6825 KdPrint(("Write16, LBA %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
6826 Cdb->CDB16READWRITE.LBA[0],
6827 Cdb->CDB16READWRITE.LBA[1],
6828 Cdb->CDB16READWRITE.LBA[2],
6829 Cdb->CDB16READWRITE.LBA[3],
6830 Cdb->CDB16READWRITE.LBA[4],
6831 Cdb->CDB16READWRITE.LBA[5],
6832 Cdb->CDB16READWRITE.LBA[6],
6833 Cdb->CDB16READWRITE.LBA[7]
6834 ));
6835 } else
6836 if(ScsiCommand == SCSIOP_MODE_SELECT) {
6837 KdPrint(("ModeSelect 6\n"));
6838 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
6839 ModeSelectData = CdbData+4;
6840 KdDump(CdbData, CdbDataLen);
6841 } else
6842 if(ScsiCommand == SCSIOP_MODE_SELECT10) {
6843 KdPrint(("ModeSelect 10\n"));
6844 PMODE_PARAMETER_HEADER ParamHdr = (PMODE_PARAMETER_HEADER)CdbData;
6845 ModeSelectData = CdbData+8;
6846 KdDump(CdbData, CdbDataLen);
6847 } else {
6848 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
6849 KdPrint(("Send buffer to device:\n"));
6850 KdDump(CdbData, CdbDataLen);
6851 }
6852 }
6853 KdPrint(("--\n"));
6854 }
6855 #endif //UNIATA_DUMP_ATAPI
6856
6857
6858 if(CmdAction == CMD_ACTION_PREPARE) {
6859 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_PREPARE, Cdb %x\n", &(Srb->Cdb)));
6860
6861 switch (Srb->Cdb[0]) {
6862 case SCSIOP_RECEIVE:
6863 case SCSIOP_SEND:
6864 case SCSIOP_READ:
6865 case SCSIOP_WRITE:
6866 case SCSIOP_READ12:
6867 case SCSIOP_WRITE12:
6868 case SCSIOP_READ16:
6869 case SCSIOP_WRITE16:
6870 // all right
6871 break;
6872 default:
6873 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY\n"));
6874 return SRB_STATUS_BUSY;
6875 }
6876 //
6877 if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
6878 !AtaReq->OriginalSrb) {
6879 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_BUSY (2)\n"));
6880 return SRB_STATUS_BUSY;
6881 }
6882 }
6883
6884 #ifndef UNIATA_CORE
6885 // We need to know how many platters our atapi cd-rom device might have.
6886 // Before anyone tries to send a srb to our target for the first time,
6887 // we must "secretly" send down a separate mechanism status srb in order to
6888 // initialize our device extension changer data. That's how we know how
6889 // many platters our target has.
6890
6891 if (!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED) &&
6892 !AtaReq->OriginalSrb) {
6893
6894 ULONG srbStatus;
6895
6896 KdPrint3((PRINT_PREFIX "AtapiSendCommand: BuildMechanismStatusSrb()\n"));
6897 // Set this flag now. If the device hangs on the mech. status
6898 // command, we will not have the chance to set it.
6899 LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
6900
6901 chan->MechStatusRetryCount = 3;
6902 AtaReq->OriginalSrb = Srb;
6903 AtaReq->Srb = BuildMechanismStatusSrb (
6904 HwDeviceExtension,
6905 Srb);
6906
6907 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AtapiSendCommand recursive\n"));
6908 srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
6909 if (srbStatus == SRB_STATUS_PENDING) {
6910 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n"));
6911 return srbStatus;
6912 } else {
6913
6914 // failed! Get the sense key and maybe try again
6915 AtaReq->Srb = BuildRequestSenseSrb ( HwDeviceExtension,
6916 AtaReq->OriginalSrb);
6917
6918 srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL);
6919
6920 KdPrint3((PRINT_PREFIX "AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt));
6921
6922 if (srbStatus == SRB_STATUS_PENDING) {
6923 KdPrint2((PRINT_PREFIX "AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n"));
6924 return srbStatus;
6925 }
6926
6927 // failed again ? should not get here
6928
6929 AtaReq->Srb = AtaReq->OriginalSrb;
6930 AtaReq->OriginalSrb = NULL;
6931
6932 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n"));
6933 // Do-nothing call ?
6934 AtapiHwInitializeChanger (HwDeviceExtension, Srb,
6935 (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL);
6936 // fall out
6937 }
6938 }
6939 #endif //UNIATA_CORE
6940
6941 if((CmdAction & CMD_ACTION_PREPARE) &&
6942 (AtaReq->ReqState != REQ_STATE_READY_TO_TRANSFER)) {
6943
6944 KdPrint2((PRINT_PREFIX "AtapiSendCommand: prepare..., ATAPI CMD %x (Cdb %x)\n", Srb->Cdb[0], &(Srb->Cdb)));
6945
6946 if(!LunExt->IdentifyData.AtapiCmdSize &&
6947 (Srb->CdbLength > 12)) {
6948 KdPrint2((PRINT_PREFIX "Cdb16 not supported\n"));
6949 return SRB_STATUS_INVALID_REQUEST;
6950 }
6951
6952 // Set data buffer pointer and words left.
6953 AtaReq->DataBuffer = (PUSHORT)Srb->DataBuffer;
6954 AtaReq->WordsLeft = Srb->DataTransferLength / 2;
6955 AtaReq->TransferLength = Srb->DataTransferLength;
6956 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
6957 // reset this to force PRD init. May be already setup by recursive SRB
6958 AtaReq->dma_entries = 0;
6959
6960 // check if reorderable
6961 switch(Srb->Cdb[0]) {
6962 case SCSIOP_READ16:
6963 case SCSIOP_WRITE16:
6964
6965 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB16READWRITE.NumOfBlocks);
6966 MOV_QD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB16READWRITE.LBA);
6967 goto GetLba2;
6968
6969 case SCSIOP_READ12:
6970 case SCSIOP_WRITE12:
6971
6972 MOV_DD_SWP(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB12READWRITE.NumOfBlocks);
6973 goto GetLba;
6974
6975 case SCSIOP_READ:
6976 case SCSIOP_WRITE:
6977
6978 MOV_SWP_DW2DD(AtaReq->bcount, ((PCDB)Srb->Cdb)->CDB10.TransferBlocks);
6979 GetLba:
6980 MOV_DD_SWP(AtaReq->lba, ((PCDB)Srb->Cdb)->CDB10.LBA);
6981 GetLba2:
6982 AtaReq->Flags |= REQ_FLAG_REORDERABLE_CMD;
6983 AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
6984 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE ||
6985 Srb->Cdb[0] == SCSIOP_WRITE12 ||
6986 Srb->Cdb[0] == SCSIOP_WRITE16) ?
6987 REQ_FLAG_WRITE : REQ_FLAG_READ;
6988 break;
6989 default:
6990 AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
6991 if(!AtaReq->TransferLength) {
6992 KdPrint((" assume 0-transfer\n"));
6993 } else
6994 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
6995 KdPrint((" assume OUT\n"));
6996 AtaReq->Flags |= REQ_FLAG_WRITE;
6997 } else
6998 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
6999 KdPrint((" assume IN\n"));
7000 AtaReq->Flags |= REQ_FLAG_READ;
7001 }
7002 break;
7003 }
7004
7005 // check if DMA read/write
7006 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7007 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (ahci)\n"));
7008 use_dma = TRUE;
7009 goto setup_dma;
7010 } else
7011 /* if((deviceExtension->HwFlags & UNIATA_SATA) && (LunExt->OrigTransferMode >= ATA_DMA)) {
7012 KdPrint2((PRINT_PREFIX "AtapiSendCommand: force use dma (sata)\n"));
7013 use_dma = TRUE;
7014 goto setup_dma;
7015 } else*/
7016 if(Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
7017 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE, no DMA setup\n"));
7018 } else
7019 if(AtaReq->TransferLength) {
7020 // try use DMA
7021 switch(Srb->Cdb[0]) {
7022 case SCSIOP_WRITE:
7023 case SCSIOP_WRITE12:
7024 case SCSIOP_WRITE16:
7025 case SCSIOP_SEND:
7026 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO)
7027 break;
7028 /* FALLTHROUGH */
7029 case SCSIOP_RECEIVE:
7030 case SCSIOP_READ:
7031 case SCSIOP_READ12:
7032 case SCSIOP_READ16:
7033
7034 if(deviceExtension->opt_AtapiDmaReadWrite) {
7035 call_dma_setup:
7036 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7037 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
7038 use_dma = TRUE;
7039 } else
7040 if(AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7041 (PUCHAR)(AtaReq->DataBuffer),
7042 Srb->DataTransferLength
7043 /*((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1))*/
7044 )) {
7045 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
7046 use_dma = TRUE;
7047 }
7048 }
7049 break;
7050 case SCSIOP_READ_CD:
7051 if(deviceExtension->opt_AtapiDmaRawRead)
7052 goto call_dma_setup;
7053 break;
7054 default:
7055
7056 if(deviceExtension->opt_AtapiDmaControlCmd) {
7057 if(Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
7058 // read operation
7059 use_dma = TRUE;
7060 } else {
7061 // write operation
7062 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_RO) {
7063 KdPrint2((PRINT_PREFIX "dma RO\n"));
7064 use_dma = FALSE;
7065 } else {
7066 use_dma = TRUE;
7067 }
7068 }
7069 }
7070 break;
7071 }
7072 // try setup DMA
7073 setup_dma:
7074 if(use_dma) {
7075 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7076 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (ahci)\n"));
7077 //use_dma = TRUE;
7078 } else
7079 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7080 (PUCHAR)(AtaReq->DataBuffer),
7081 Srb->DataTransferLength)) {
7082 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma\n"));
7083 use_dma = FALSE;
7084 } else {
7085 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma\n"));
7086 }
7087 }
7088 } else {
7089 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer, no DMA setup\n"));
7090 }
7091
7092
7093 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7094
7095 UniataAhciSetupCmdPtr(AtaReq);
7096
7097 if(!Srb->DataTransferLength) {
7098 KdPrint2((PRINT_PREFIX "zero-transfer\n"));
7099 use_dma = FALSE;
7100 } else
7101 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
7102 (PUCHAR)(AtaReq->DataBuffer),
7103 Srb->DataTransferLength)) {
7104 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no AHCI dma!\n"));
7105 return SRB_STATUS_ERROR;
7106 }
7107 if(!use_dma) {
7108 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7109 } else {
7110 FeatureReg |= ATA_F_DMA;
7111 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired &&
7112 (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
7113 FeatureReg |= ATA_F_DMAREAD;
7114 }
7115 }
7116
7117 KdPrint2((PRINT_PREFIX "AtapiSendCommand: setup AHCI FIS\n"));
7118 // this is done in UniataAhciSetupFIS_H2D()
7119 //RtlZeroMemory(&(AtaReq->ahci.ahci_cmd_ptr->cfis), sizeof(AtaReq->ahci_cmd0.cfis));
7120 RtlCopyMemory(&(AtaReq->ahci.ahci_cmd_ptr->acmd), Srb->Cdb, Srb->CdbLength);
7121
7122 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel,
7123 &(AtaReq->ahci.ahci_cmd_ptr->cfis[0]),
7124 IDE_COMMAND_ATAPI_PACKET /* command */,
7125 0 /* lba */,
7126 (Srb->DataTransferLength >= 0x10000) ? (USHORT)(0xffff) : (USHORT)(Srb->DataTransferLength),
7127 FeatureReg/* feature */
7128 );
7129
7130 if(!fis_size) {
7131 KdPrint3((PRINT_PREFIX "AtapiSendCommand: AHCI !FIS\n"));
7132 return SRB_STATUS_ERROR;
7133 }
7134
7135 AtaReq->ahci.io_cmd_flags = UniAtaAhciAdjustIoFlags(0,
7136 ((Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)) ? ATA_AHCI_CMD_WRITE : 0) |
7137 (ATA_AHCI_CMD_ATAPI | ATA_AHCI_CMD_PREFETCH),
7138 fis_size, DeviceNumber);
7139
7140 KdPrint2((PRINT_PREFIX "AtapiSendCommand ahci io flags %x: \n", AtaReq->ahci.io_cmd_flags));
7141 }
7142
7143 } else {
7144 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7145 // if this is queued request, reinit DMA and check
7146 // if DMA mode is still available
7147 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() (1)\n"));
7148 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7149 if (/*EnableDma &&*/
7150 (LunExt->TransferMode >= ATA_DMA)) {
7151 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use dma (2)\n"));
7152 use_dma = TRUE;
7153 } else {
7154 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7155 KdPrint2((PRINT_PREFIX "AtapiSendCommand: no dma (2)\n"));
7156 use_dma = FALSE;
7157 }
7158 dma_reinited = TRUE;
7159 }
7160 }
7161
7162 if(!(CmdAction & CMD_ACTION_EXEC)) {
7163 KdPrint2((PRINT_PREFIX "AtapiSendCommand: !CMD_ACTION_EXEC => SRB_STATUS_PENDING\n"));
7164 return SRB_STATUS_PENDING;
7165 }
7166 KdPrint3((PRINT_PREFIX "AtapiSendCommand: use_dma=%d, Cmd %x\n", use_dma, Srb->Cdb[0]));
7167 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7168 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
7169 }
7170
7171 if((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) && !(deviceExtension->HwFlags & UNIATA_SATA)) {
7172 KdPrint2((PRINT_PREFIX "AtapiSendCommand: SCSIOP_REQUEST_SENSE -> no dma setup (2)\n"));
7173 use_dma = FALSE;
7174 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7175 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7176 } if(AtaReq->TransferLength) {
7177 if(!dma_reinited) {
7178 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit()\n"));
7179 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7180 if (/*EnableDma &&*/
7181 (LunExt->TransferMode >= ATA_DMA)) {
7182 use_dma = TRUE;
7183 } else {
7184 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7185 use_dma = FALSE;
7186 }
7187 }
7188 } else {
7189 KdPrint2((PRINT_PREFIX "AtapiSendCommand: zero transfer\n"));
7190 use_dma = FALSE;
7191 AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
7192 if(!deviceExtension->opt_AtapiDmaZeroTransfer && !(deviceExtension->HwFlags & UNIATA_SATA)) {
7193 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiDmaReinit() to PIO\n"));
7194 AtapiDmaReinit(deviceExtension, LunExt, AtaReq);
7195 }
7196 }
7197 KdPrint2((PRINT_PREFIX "AtapiSendCommand: use_dma=%d\n", use_dma));
7198 if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
7199 KdPrint2((PRINT_PREFIX " REQ_FLAG_DMA_OPERATION\n"));
7200 }
7201
7202 KdPrint2((PRINT_PREFIX "AtapiSendCommand: CMD_ACTION_EXEC\n"));
7203
7204 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Cdb %x Command %#x to TargetId %d lun %d\n",
7205 &(Srb->Cdb), Srb->Cdb[0], Srb->TargetId, Srb->Lun));
7206
7207 // Make sure command is to ATAPI device.
7208 flags = LunExt->DeviceFlags;
7209 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
7210 if((Srb->Lun) > (LunExt->DiscsPresent - 1)) {
7211
7212 // Indicate no device found at this address.
7213 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7214 return SRB_STATUS_SELECTION_TIMEOUT;
7215 }
7216 } else if(Srb->Lun > 0) {
7217 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7218 return SRB_STATUS_SELECTION_TIMEOUT;
7219 }
7220
7221 if(!(flags & DFLAGS_ATAPI_DEVICE)) {
7222 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7223 return SRB_STATUS_SELECTION_TIMEOUT;
7224 }
7225 retry:
7226 // Select device 0 or 1. Or more for PM
7227 SelectDrive(chan, DeviceNumber);
7228
7229 // Verify that controller is ready for next command.
7230 GetStatus(chan, statusByte);
7231 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status %#x\n", statusByte));
7232
7233 if(statusByte == IDE_STATUS_WRONG) {
7234 KdPrint2((PRINT_PREFIX "AtapiSendCommand: bad status 0xff on entry\n"));
7235 goto make_reset;
7236 }
7237 if(statusByte & IDE_STATUS_BUSY) {
7238 if(statusByte & IDE_STATUS_DSC) {
7239 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC on entry (%#x), try exec\n", statusByte));
7240 } else {
7241 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Device busy (%#x) -> reset\n", statusByte));
7242 // We have to make reset here, since we are expecting device to be available
7243 //return SRB_STATUS_BUSY; // this cause queue freeze
7244 goto make_reset;
7245 }
7246 }
7247 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7248 ULONG CI;
7249 // Check if command list is free
7250 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI);
7251 if(CI) {
7252 // controller is busy, however we expect it to be free
7253 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Controller busy (CI=%#x) -> reset\n", CI));
7254 goto make_reset;
7255 }
7256 }
7257 if(statusByte & IDE_STATUS_ERROR) {
7258 if (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE) {
7259
7260 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on entry: (%#x)\n", statusByte));
7261 // Read the error reg. to clear it and fail this request.
7262 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7263 return MapError(deviceExtension, Srb);
7264 } else {
7265 KdPrint2((PRINT_PREFIX " continue with SCSIOP_REQUEST_SENSE\n", statusByte));
7266 }
7267 }
7268 // If a tape drive doesn't have DSC set and the last command is restrictive, don't send
7269 // the next command. See discussion of Restrictive Delayed Process commands in QIC-157.
7270 if((!(statusByte & IDE_STATUS_DSC)) &&
7271 (flags & (DFLAGS_TAPE_DEVICE | DFLAGS_ATAPI_DEVICE)) && chan->RDP) {
7272
7273 AtapiStallExecution(200);
7274 KdPrint2((PRINT_PREFIX "AtapiSendCommand: DSC not set. %#x => SRB_STATUS_PENDING\n",statusByte));
7275 AtaReq->ReqState = REQ_STATE_QUEUED;
7276 return SRB_STATUS_PENDING;
7277 }
7278
7279 if(IS_RDP(Srb->Cdb[0])) {
7280 chan->RDP = TRUE;
7281 KdPrint2((PRINT_PREFIX "AtapiSendCommand: %#x mapped as DSC restrictive\n", Srb->Cdb[0]));
7282 } else {
7283 chan->RDP = FALSE;
7284 }
7285 if(statusByte & IDE_STATUS_DRQ) {
7286
7287 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entered with status (%#x). Attempting to recover.\n",
7288 statusByte));
7289 // Try to drain the data that one preliminary device thinks that it has
7290 // to transfer. Hopefully this random assertion of DRQ will not be present
7291 // in production devices.
7292 statusByte = AtapiSuckPort2(chan);
7293 /*
7294 for (i = 0; i < 0x10000; i++) {
7295 GetStatus(chan, statusByte);
7296 if(statusByte & IDE_STATUS_DRQ) {
7297 AtapiReadPort2(chan, IDX_IO1_i_Data);
7298 } else {
7299 break;
7300 }
7301 }
7302 */
7303 if (statusByte & IDE_STATUS_DRQ) {
7304 make_reset:
7305 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ still asserted.Status (%#x)\n", statusByte));
7306
7307 AtapiDisableInterrupts(deviceExtension, lChannel);
7308
7309 AtapiSoftReset(chan, DeviceNumber);
7310
7311 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Issued soft reset to Atapi device. \n"));
7312 // Re-initialize Atapi device.
7313 CheckDevice(HwDeviceExtension, GET_CHANNEL(Srb), DeviceNumber, TRUE);
7314 /*
7315 IssueIdentify(HwDeviceExtension, DeviceNumber, GET_CHANNEL(Srb),
7316 IDE_COMMAND_ATAPI_IDENTIFY, FALSE);
7317 */
7318 // Inform the port driver that the bus has been reset.
7319 ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
7320 // Clean up device extension fields that AtapiStartIo won't.
7321 UniataExpectChannelInterrupt(chan, FALSE);
7322 chan->RDP = FALSE;
7323 InterlockedExchange(&(deviceExtension->chan[GET_CHANNEL(Srb)].CheckIntr),
7324 CHECK_INTR_IDLE);
7325
7326 AtapiEnableInterrupts(deviceExtension, lChannel);
7327 /*
7328 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7329 return SRB_STATUS_BUS_RESET;
7330 */
7331 if(!retried) {
7332 KdPrint3((PRINT_PREFIX "AtapiSendCommand: retry after reset.\n"));
7333 retried = TRUE;
7334 goto retry;
7335 }
7336 KdPrint3((PRINT_PREFIX "AtapiSendCommand: selection timeout.\n"));
7337 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7338 return SRB_STATUS_SELECTION_TIMEOUT;
7339 }
7340 }
7341
7342 if(flags & (DFLAGS_SANYO_ATAPI_CHANGER | DFLAGS_ATAPI_CHANGER)) {
7343 // As the cdrom driver sets the LUN field in the cdb, it must be removed.
7344 Srb->Cdb[1] &= ~0xE0;
7345 if((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY) && (flags & DFLAGS_SANYO_ATAPI_CHANGER)) {
7346 // Torisan changer. TUR's are overloaded to be platter switches.
7347 Srb->Cdb[7] = Srb->Lun;
7348 }
7349 }
7350
7351 // SETUP DMA !!!!!
7352
7353 if(use_dma) {
7354 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_OPERATION;
7355 } else {
7356 chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION;
7357 }
7358
7359 if(deviceExtension->HwFlags & UNIATA_AHCI) {
7360 KdPrint2((PRINT_PREFIX "AtapiSendCommand: AHCI, begin transaction\n"));
7361 //AtaReq->Flags = ~REQ_FLAG_DMA_OPERATION; // keep proped DMA flag for proper RETRY handling
7362 UniataExpectChannelInterrupt(chan, TRUE);
7363 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb);
7364 return SRB_STATUS_PENDING;
7365 }
7366
7367 statusByte = WaitOnBusy(chan);
7368 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Entry Status (%#x)\n",
7369 statusByte));
7370
7371 if(use_dma) {
7372 FeatureReg |= ATA_F_DMA;
7373 if(LunExt->IdentifyData.AtapiDMA.DMADirRequired &&
7374 (Srb->SrbFlags & SRB_FLAGS_DATA_IN)) {
7375 FeatureReg |= ATA_F_DMAREAD;
7376 }
7377 }
7378
7379 AtapiWritePort1(chan, IDX_IO1_o_Feature, FeatureReg);
7380
7381 // Write transfer byte count to registers.
7382 byteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
7383 byteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
7384
7385 if (Srb->DataTransferLength >= 0x10000) {
7386 byteCountLow = byteCountHigh = 0xFF;
7387 }
7388
7389 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountLow, byteCountLow);
7390 AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, byteCountHigh);
7391
7392 if (flags & DFLAGS_INT_DRQ) {
7393
7394 // This device interrupts when ready to receive the packet.
7395
7396 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Wait for int. to send packet. Status (%#x)\n",
7397 statusByte));
7398
7399 UniataExpectChannelInterrupt(chan, TRUE);
7400 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_CMD_INTR;
7401 InterlockedExchange(&(chan->CheckIntr),
7402 CHECK_INTR_IDLE);
7403
7404 // Write ATAPI packet command.
7405 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
7406
7407 KdPrint3((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (DRQ)\n"));
7408 return SRB_STATUS_PENDING;
7409
7410 }
7411
7412 // This device quickly sets DRQ when ready to receive the packet.
7413
7414 KdPrint2((PRINT_PREFIX "AtapiSendCommand: Poll for int. to send packet. Status (%#x)\n",
7415 statusByte));
7416
7417 UniataExpectChannelInterrupt(chan, TRUE);
7418 AtaReq->ReqState = REQ_STATE_ATAPI_DO_NOTHING_INTR;
7419 InterlockedExchange(&(chan->CheckIntr),
7420 CHECK_INTR_IDLE);
7421
7422 if(g_opt_AtapiSendDisableIntr) {
7423 AtapiDisableInterrupts(deviceExtension, lChannel);
7424 }
7425 // remember status. Later we may check if error appeared after cmd packet
7426 statusByte0 = statusByte;
7427
7428 // Write ATAPI packet command.
7429 AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET);
7430
7431 // Wait for DRQ.
7432 WaitOnBusy(chan);
7433 statusByte = WaitForDrq(chan);
7434
7435 // Need to read status register and clear interrupt (if any)
7436 GetBaseStatus(chan, statusByte);
7437
7438 if (!(statusByte & IDE_STATUS_DRQ)) {
7439
7440 if(g_opt_AtapiSendDisableIntr) {
7441 AtapiEnableInterrupts(deviceExtension, lChannel);
7442 }
7443 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DRQ never asserted (%#x)\n", statusByte));
7444 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7445 return SRB_STATUS_ERROR;
7446 }
7447
7448 GetStatus(chan, statusByte);
7449 KdPrint3((PRINT_PREFIX "AtapiSendCommand: status (%#x)\n", statusByte));
7450
7451 // Send CDB to device.
7452 statusByte = WaitOnBaseBusy(chan);
7453
7454 // Indicate expecting an interrupt and wait for it.
7455 UniataExpectChannelInterrupt(chan, TRUE);
7456 InterlockedExchange(&(chan->CheckIntr),
7457 CHECK_INTR_IDLE);
7458 AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
7459
7460 GetBaseStatus(chan, statusByte);
7461
7462 if(g_opt_AtapiSendDisableIntr) {
7463 AtapiEnableInterrupts(deviceExtension, lChannel);
7464 }
7465
7466 WriteBuffer(chan,
7467 (PUSHORT)Srb->Cdb,
7468 LunExt->IdentifyData.AtapiCmdSize ? 8 : 6,
7469 0);
7470
7471 GetStatus(chan, statusByte);
7472 KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte));
7473
7474 // When we operate in DMA mode, we should not start transfer when there is an error on entry
7475 // Interrupt may never come in such case.
7476 if(statusByte & IDE_STATUS_ERROR) {
7477 UCHAR interruptReason;
7478
7479 GetBaseStatus(chan, statusByte);
7480 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on cmd: (%#x)\n", statusByte));
7481
7482 interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask);
7483 KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", interruptReason));
7484
7485 // TODO: we should check interruptReason and decide what to do now
7486
7487 // Read the error reg. to clear it and fail this request.
7488 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7489 return MapError(deviceExtension, Srb);
7490 }
7491 /* if(statusByte & IDE_STATUS_DSC) {
7492 KdPrint3((PRINT_PREFIX "AtapiSendCommand: DSC on cmd: (%#x)\n", statusByte));
7493 // Read the error reg. to clear it and fail this request.
7494 statusByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7495 KdPrint3((PRINT_PREFIX "AtapiSendCommand: Err on cmd: (%#x)\n", statusByte));
7496 if(statusByte >> 4) {
7497 GetBaseStatus(chan, statusByte);
7498 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
7499 return MapError(deviceExtension, Srb);
7500 }
7501 }
7502 */
7503 if(chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION) {
7504 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
7505 }
7506
7507 KdPrint3((PRINT_PREFIX "AtapiSendCommand: ExpectingInterrupt (%#x)\n", chan->ExpectingInterrupt));
7508
7509 KdPrint2((PRINT_PREFIX "AtapiSendCommand: return SRB_STATUS_PENDING (3)\n"));
7510 return SRB_STATUS_PENDING;
7511
7512 } // end AtapiSendCommand()
7513
7514
7515 #ifndef UNIATA_CORE
7516
7517 /*++
7518
7519 Routine Description:
7520 Program ATA registers for IDE disk transfer.
7521
7522 Arguments:
7523 HwDeviceExtension - ATAPI driver storage.
7524 Srb - System request block.
7525
7526 Return Value:
7527 SRB status (pending if all goes well).
7528
7529 --*/
7530
7531 #ifdef _DEBUG
7532 ULONG check_point = 0;
7533 #define SetCheckPoint(cp) { check_point = (cp) ; }
7534 #else
7535 #define SetCheckPoint(cp)
7536 #endif
7537
7538 ULONG
7539 NTAPI
7540 IdeSendCommand(
7541 IN PVOID HwDeviceExtension,
7542 IN PSCSI_REQUEST_BLOCK Srb,
7543 IN ULONG CmdAction
7544 )
7545 {
7546 SetCheckPoint(1);
7547 KdPrint2((PRINT_PREFIX "** Ide: Command: entryway\n"));
7548 SetCheckPoint(2);
7549
7550 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
7551 SetCheckPoint(3);
7552 UCHAR lChannel;
7553 PHW_CHANNEL chan;
7554 PCDB cdb;
7555 PHW_LU_EXTENSION LunExt;
7556
7557 SetCheckPoint(4);
7558
7559 UCHAR statusByte,errorByte;
7560 ULONG status = SRB_STATUS_INVALID_REQUEST;
7561 ULONG i;
7562 ULONGLONG lba;
7563 PMODE_PARAMETER_HEADER modeData;
7564 //ULONG ldev;
7565 ULONG DeviceNumber;
7566 PATA_REQ AtaReq;
7567 UCHAR command;
7568
7569 SetCheckPoint(5);
7570 //ULONG __ebp__ = 0;
7571
7572 SetCheckPoint(0x20);
7573 KdPrint2((PRINT_PREFIX "** Ide: Command:\n\n"));
7574 /* __asm {
7575 mov eax,ebp
7576 mov __ebp__, eax
7577 }*/
7578 /*KdPrint2((PRINT_PREFIX "** Ide: Command EBP %#x, pCdb %#x, cmd %#x\n",
7579 __ebp__, &(Srb->Cdb[0]), Srb->Cdb[0]));
7580 KdPrint2((PRINT_PREFIX "** Ide: Command %s\n",
7581 (CmdAction == CMD_ACTION_PREPARE) ? "Prep " : ""));
7582 KdPrint2((PRINT_PREFIX "** Ide: Command Srb %#x\n",
7583 Srb));
7584 KdPrint2((PRINT_PREFIX "** Ide: Command SrbExt %#x\n",
7585 Srb->SrbExtension));
7586 KdPrint2((PRINT_PREFIX "** Ide: Command to device %d\n",
7587 Srb->TargetId));*/
7588
7589 SetCheckPoint(0x30);
7590 AtaReq = (PATA_REQ)(Srb->SrbExtension);
7591
7592 KdPrint2((PRINT_PREFIX "** Ide: Command &AtaReq %#x\n",
7593 &AtaReq));
7594 KdPrint2((PRINT_PREFIX "** Ide: Command AtaReq %#x\n",
7595 AtaReq));
7596 KdPrint2((PRINT_PREFIX "** --- **\n"));
7597
7598 lChannel = GET_CHANNEL(Srb);
7599 chan = &(deviceExtension->chan[lChannel]);
7600 //ldev = GET_LDEV(Srb);
7601 DeviceNumber = GET_CDEV(Srb);
7602 LunExt = chan->lun[DeviceNumber];
7603
7604 SetCheckPoint(0x40);
7605 if(AtaReq->ReqState < REQ_STATE_PREPARE_TO_TRANSFER)
7606 AtaReq->ReqState = REQ_STATE_PREPARE_TO_TRANSFER;
7607
7608 cdb = (PCDB)(Srb->Cdb);
7609
7610 if(CmdAction == CMD_ACTION_PREPARE) {
7611 switch (Srb->Cdb[0]) {
7612 case SCSIOP_SERVICE_ACTION16:
7613 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) {
7614 // ok
7615 } else {
7616 goto default_no_prep;
7617 }
7618 #ifdef NAVO_TEST
7619 case SCSIOP_INQUIRY: // now it requires device access
7620 #endif //NAVO_TEST
7621 case SCSIOP_READ_CAPACITY:
7622 case SCSIOP_READ:
7623 case SCSIOP_WRITE:
7624 case SCSIOP_READ12:
7625 case SCSIOP_WRITE12:
7626 case SCSIOP_READ16:
7627 case SCSIOP_WRITE16:
7628 case SCSIOP_REQUEST_SENSE:
7629 // all right
7630 KdPrint2((PRINT_PREFIX "** Ide: Command continue prep\n"));
7631 SetCheckPoint(50);
7632 break;
7633 default:
7634 default_no_prep:
7635 SetCheckPoint(0);
7636 KdPrint2((PRINT_PREFIX "** Ide: Command break prep\n"));
7637 return SRB_STATUS_BUSY;
7638 }
7639 }
7640
7641 SetCheckPoint(0x100 | Srb->Cdb[0]);
7642 switch (Srb->Cdb[0]) {
7643 case SCSIOP_INQUIRY:
7644
7645 KdPrint2((PRINT_PREFIX
7646 "IdeSendCommand: SCSIOP_INQUIRY PATH:LUN:TID = %#x:%#x:%#x\n",
7647 Srb->PathId, Srb->Lun, Srb->TargetId));
7648 // Filter out wrong TIDs.
7649 if ((Srb->Lun != 0) ||
7650 (Srb->PathId >= deviceExtension->NumberChannels) ||
7651 (Srb->TargetId >= deviceExtension->NumberLuns)) {
7652
7653 KdPrint2((PRINT_PREFIX
7654 "IdeSendCommand: SCSIOP_INQUIRY rejected\n"));
7655 // Indicate no device found at this address.
7656 status = SRB_STATUS_SELECTION_TIMEOUT;
7657 break;
7658
7659 } else {
7660
7661 KdPrint2((PRINT_PREFIX
7662 "IdeSendCommand: SCSIOP_INQUIRY ok\n"));
7663 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
7664 PIDENTIFY_DATA2 identifyData = &(LunExt->IdentifyData);
7665
7666 if (!(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
7667
7668 if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
7669 KdPrint2((PRINT_PREFIX
7670 "IdeSendCommand: SCSIOP_INQUIRY rejected (2)\n"));
7671 // Indicate no device found at this address.
7672 #ifndef NAVO_TEST
7673 status = SRB_STATUS_SELECTION_TIMEOUT;
7674 break;
7675 }
7676 } else {
7677 if(!UniataAnybodyHome(HwDeviceExtension, lChannel, DeviceNumber)) {
7678 KdPrint2((PRINT_PREFIX
7679 "IdeSendCommand: SCSIOP_INQUIRY device have gone\n"));
7680 // Indicate no device found at this address.
7681 UniataForgetDevice(chan->lun[DeviceNumber]);
7682 #endif //NAVO_TEST
7683 status = SRB_STATUS_SELECTION_TIMEOUT;
7684 break;
7685 }
7686 }
7687
7688 // Zero INQUIRY data structure.
7689 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
7690
7691 // Standard IDE interface only supports disks.
7692 inquiryData->DeviceType = DIRECT_ACCESS_DEVICE;
7693
7694 // Set the removable bit, if applicable.
7695 if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
7696 KdPrint2((PRINT_PREFIX
7697 "RemovableMedia\n"));
7698 inquiryData->RemovableMedia = 1;
7699 }
7700 // Set the Relative Addressing (LBA) bit, if applicable.
7701 if (LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) {
7702 inquiryData->RelativeAddressing = 1;
7703 KdPrint2((PRINT_PREFIX
7704 "RelativeAddressing\n"));
7705 }
7706 // Set the CommandQueue bit
7707 inquiryData->CommandQueue = 1;
7708
7709 // Fill in vendor identification fields.
7710 for (i = 0; i < 24; i += 2) {
7711 MOV_DW_SWP(inquiryData->DeviceIdentificationString[i], ((PUCHAR)identifyData->ModelNumber)[i]);
7712 }
7713 /*
7714 // Initialize unused portion of product id.
7715 for (i = 0; i < 4; i++) {
7716 inquiryData->ProductId[12+i] = ' ';
7717 }
7718 */
7719 // Move firmware revision from IDENTIFY data to
7720 // product revision in INQUIRY data.
7721 for (i = 0; i < 4; i += 2) {
7722 MOV_DW_SWP(inquiryData->ProductRevisionLevel[i], ((PUCHAR)identifyData->FirmwareRevision)[i]);
7723 }
7724
7725 status = SRB_STATUS_SUCCESS;
7726 }
7727
7728 break;
7729
7730 case SCSIOP_REPORT_LUNS: {
7731
7732 ULONG alen;
7733 PREPORT_LUNS_INFO_HDR LunInfo;
7734
7735 KdPrint2((PRINT_PREFIX
7736 "IdeSendCommand: SCSIOP_REPORT_LUNS PATH:LUN:TID = %#x:%#x:%#x\n",
7737 Srb->PathId, Srb->Lun, Srb->TargetId));
7738
7739 MOV_DD_SWP(alen, cdb->REPORT_LUNS.AllocationLength);
7740
7741 if(alen < 16) {
7742 goto invalid_cdb;
7743 }
7744 alen = 8;
7745
7746 LunInfo = (PREPORT_LUNS_INFO_HDR)(Srb->DataBuffer);
7747 RtlZeroMemory(LunInfo, 16);
7748
7749 MOV_DD_SWP( LunInfo->ListLength, alen );
7750 Srb->DataTransferLength = 16;
7751 status = SRB_STATUS_SUCCESS;
7752
7753 break; }
7754
7755 case SCSIOP_MODE_SENSE:
7756
7757 KdPrint2((PRINT_PREFIX
7758 "IdeSendCommand: SCSIOP_MODE_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
7759 Srb->PathId, Srb->Lun, Srb->TargetId));
7760
7761 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_POWER_CONDITION) {
7762 PMODE_POWER_CONDITION_PAGE modeData;
7763
7764 KdPrint2((PRINT_PREFIX "MODE_PAGE_POWER_CONDITION\n"));
7765 modeData = (PMODE_POWER_CONDITION_PAGE)(Srb->DataBuffer);
7766 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_POWER_CONDITION_PAGE)) {
7767 status = SRB_STATUS_DATA_OVERRUN;
7768 } else {
7769 RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE));
7770 modeData->PageCode = MODE_PAGE_POWER_CONDITION;
7771 modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER);
7772 modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle;
7773 modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby;
7774 Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE);
7775 status = SRB_STATUS_SUCCESS;
7776 }
7777 } else
7778 if(cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) {
7779 PMODE_CACHING_PAGE modeData;
7780
7781 KdPrint2((PRINT_PREFIX "MODE_PAGE_CACHING\n"));
7782 modeData = (PMODE_CACHING_PAGE)(Srb->DataBuffer);
7783 if(cdb->MODE_SENSE.AllocationLength < sizeof(MODE_CACHING_PAGE)) {
7784 status = SRB_STATUS_DATA_OVERRUN;
7785 } else {
7786 RtlZeroMemory(modeData, sizeof(MODE_CACHING_PAGE));
7787 modeData->PageCode = MODE_PAGE_CACHING;
7788 modeData->PageLength = sizeof(MODE_CACHING_PAGE)-sizeof(MODE_PARAMETER_HEADER);
7789 modeData->ReadDisableCache = (LunExt->DeviceFlags & DFLAGS_RCACHE_ENABLED) ? 0 : 1;
7790 modeData->WriteCacheEnable = (LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) ? 1 : 0;
7791 Srb->DataTransferLength = sizeof(MODE_CACHING_PAGE);
7792 status = SRB_STATUS_SUCCESS;
7793 }
7794 } else
7795 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
7796
7797 // This is used to determine if the media is write-protected.
7798 // Since IDE does not support mode sense then we will modify just the portion we need
7799 // so the higher level driver can determine if media is protected.
7800
7801 //SelectDrive(chan, DeviceNumber);
7802 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7803 //statusByte = WaitOnBusy(chan);
7804 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
7805
7806 if (!(statusByte & IDE_STATUS_ERROR)) {
7807
7808 // no error occured return success, media is not protected
7809 UniataExpectChannelInterrupt(chan, FALSE);
7810 InterlockedExchange(&(chan->CheckIntr),
7811 CHECK_INTR_IDLE);
7812 status = SRB_STATUS_SUCCESS;
7813
7814 } else {
7815
7816 // error occured, handle it locally, clear interrupt
7817 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7818
7819 GetBaseStatus(chan, statusByte);
7820 UniataExpectChannelInterrupt(chan, FALSE);
7821 InterlockedExchange(&(chan->CheckIntr),
7822 CHECK_INTR_IDLE);
7823 status = SRB_STATUS_SUCCESS;
7824
7825 if (errorByte & IDE_ERROR_DATA_ERROR) {
7826
7827 //media is write-protected, set bit in mode sense buffer
7828 modeData = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
7829
7830 Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER);
7831 modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT;
7832 }
7833 }
7834 status = SRB_STATUS_SUCCESS;
7835 } else {
7836 status = SRB_STATUS_INVALID_REQUEST;
7837 }
7838 break;
7839
7840 case SCSIOP_TEST_UNIT_READY:
7841
7842 KdPrint2((PRINT_PREFIX
7843 "IdeSendCommand: SCSIOP_TEST_UNIT_READY PATH:LUN:TID = %#x:%#x:%#x\n",
7844 Srb->PathId, Srb->Lun, Srb->TargetId));
7845 if (chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
7846
7847 // Select device 0 or 1.
7848 //SelectDrive(chan, DeviceNumber);
7849 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_GET_MEDIA_STATUS);
7850 // Wait for busy. If media has not changed, return success
7851 //statusByte = WaitOnBusy(chan);
7852 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_GET_MEDIA_STATUS, 0, 0, 0, 0, 0, ATA_WAIT_READY);
7853
7854 if (!(statusByte & IDE_STATUS_ERROR)){
7855 UniataExpectChannelInterrupt(chan, FALSE);
7856 InterlockedExchange(&(chan->CheckIntr),
7857 CHECK_INTR_IDLE);
7858 status = SRB_STATUS_SUCCESS;
7859 } else {
7860 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
7861 if (errorByte == IDE_ERROR_DATA_ERROR){
7862
7863 // Special case: If current media is write-protected,
7864 // the 0xDA command will always fail since the write-protect bit
7865 // is sticky,so we can ignore this error
7866 GetBaseStatus(chan, statusByte);
7867 UniataExpectChannelInterrupt(chan, FALSE);
7868 InterlockedExchange(&(chan->CheckIntr),
7869 CHECK_INTR_IDLE);
7870 status = SRB_STATUS_SUCCESS;
7871
7872 } else {
7873
7874 // Request sense buffer to be build
7875 UniataExpectChannelInterrupt(chan, TRUE);
7876 InterlockedExchange(&(chan->CheckIntr),
7877 CHECK_INTR_IDLE);
7878 status = SRB_STATUS_PENDING;
7879 }
7880 }
7881 } else {
7882 status = SRB_STATUS_SUCCESS;
7883 }
7884
7885 break;
7886
7887 case SCSIOP_READ_CAPACITY:
7888
7889 KdPrint2((PRINT_PREFIX
7890 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7891 Srb->PathId, Srb->Lun, Srb->TargetId));
7892 // Claim 512 byte blocks (big-endian).
7893 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7894 i = DEV_BSIZE;
7895 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY_DATA));
7896 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock, i );
7897
7898 // Calculate last sector.
7899 if(!(i = (ULONG)LunExt->NumOfSectors)) {
7900 i = LunExt->IdentifyData.SectorsPerTrack *
7901 LunExt->IdentifyData.NumberOfHeads *
7902 LunExt->IdentifyData.NumberOfCylinders;
7903 }
7904 i--;
7905
7906 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress =
7907 // (((PUCHAR)&i)[0] << 24) | (((PUCHAR)&i)[1] << 16) |
7908 // (((PUCHAR)&i)[2] << 8) | ((PUCHAR)&i)[3];
7909
7910 MOV_DD_SWP( ((PREAD_CAPACITY_DATA)Srb->DataBuffer)->LogicalBlockAddress, i );
7911
7912 KdPrint2((PRINT_PREFIX
7913 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x\n",
7914 Srb->TargetId,
7915 LunExt->IdentifyData.SectorsPerTrack,
7916 LunExt->IdentifyData.NumberOfHeads,
7917 LunExt->IdentifyData.NumberOfCylinders));
7918
7919
7920 status = SRB_STATUS_SUCCESS;
7921 break;
7922
7923 case SCSIOP_SERVICE_ACTION16:
7924
7925 if( cdb->SERVICE_ACTION16.ServiceAction==SCSIOP_SA_READ_CAPACITY16 ) {
7926 KdPrint2((PRINT_PREFIX
7927 "** IdeSendCommand: SCSIOP_READ_CAPACITY PATH:LUN:TID = %#x:%#x:%#x\n",
7928 Srb->PathId, Srb->Lun, Srb->TargetId));
7929 // Claim 512 byte blocks (big-endian).
7930 //((PREAD_CAPACITY_DATA)Srb->DataBuffer)->BytesPerBlock = 0x20000;
7931 i = DEV_BSIZE;
7932 RtlZeroMemory(Srb->DataBuffer, sizeof(READ_CAPACITY16_DATA));
7933 MOV_DD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->BytesPerBlock, i );
7934
7935 // Calculate last sector.
7936 if(!(lba = LunExt->NumOfSectors)) {
7937 lba = LunExt->IdentifyData.SectorsPerTrack *
7938 LunExt->IdentifyData.NumberOfHeads *
7939 LunExt->IdentifyData.NumberOfCylinders;
7940 }
7941 lba--;
7942 MOV_QD_SWP( ((PREAD_CAPACITY16_DATA)Srb->DataBuffer)->LogicalBlockAddress, lba );
7943
7944 KdPrint2((PRINT_PREFIX
7945 "** IDE disk %#x - #sectors %#x, #heads %#x, #cylinders %#x (16)\n",
7946 Srb->TargetId,
7947 LunExt->IdentifyData.SectorsPerTrack,
7948 LunExt->IdentifyData.NumberOfHeads,
7949 LunExt->IdentifyData.NumberOfCylinders));
7950
7951 status = SRB_STATUS_SUCCESS;
7952 } else {
7953 goto default_abort;
7954 }
7955 break;
7956
7957 case SCSIOP_VERIFY:
7958 case SCSIOP_VERIFY12:
7959 case SCSIOP_VERIFY16:
7960
7961 KdPrint2((PRINT_PREFIX
7962 "IdeSendCommand: SCSIOP_VERIFY PATH:LUN:TID = %#x:%#x:%#x\n",
7963 Srb->PathId, Srb->Lun, Srb->TargetId));
7964 status = IdeVerify(HwDeviceExtension,Srb);
7965
7966 break;
7967
7968 case SCSIOP_READ:
7969 case SCSIOP_WRITE:
7970 case SCSIOP_READ12:
7971 case SCSIOP_WRITE12:
7972 case SCSIOP_READ16:
7973 case SCSIOP_WRITE16:
7974
7975 KdPrint2((PRINT_PREFIX
7976 "IdeSendCommand: SCSIOP_%s PATH:LUN:TID = %#x:%#x:%#x\n",
7977 (Srb->Cdb[0] == SCSIOP_WRITE) ? "WRITE" : "READ",
7978 Srb->PathId, Srb->Lun, Srb->TargetId));
7979 AtaReq->Flags &= ~REQ_FLAG_RW_MASK;
7980 AtaReq->Flags |= (Srb->Cdb[0] == SCSIOP_WRITE ||
7981 Srb->Cdb[0] == SCSIOP_WRITE12 ||
7982 Srb->Cdb[0] == SCSIOP_WRITE16) ? REQ_FLAG_WRITE : REQ_FLAG_READ;
7983 status = IdeReadWrite(HwDeviceExtension,
7984 Srb, CmdAction);
7985 break;
7986
7987 case SCSIOP_START_STOP_UNIT:
7988
7989 KdPrint2((PRINT_PREFIX
7990 "IdeSendCommand: SCSIOP_START_STOP_UNIT immed %d PATH:LUN:TID = %#x:%#x:%#x\n",
7991 cdb->START_STOP.Immediate, Srb->PathId, Srb->Lun, Srb->TargetId));
7992 //Determine what type of operation we should perform
7993
7994 command = 0;
7995
7996 if(cdb->START_STOP.FL ||
7997 cdb->START_STOP.FormatLayerNumber ||
7998 cdb->START_STOP.Reserved2 ||
7999 cdb->START_STOP.Reserved2_2 ||
8000 cdb->START_STOP.Reserved3 ||
8001 FALSE) {
8002 goto invalid_cdb;
8003 }
8004
8005 if (cdb->START_STOP.PowerConditions) {
8006 KdPrint2((PRINT_PREFIX "START_STOP Power %d\n", cdb->START_STOP.PowerConditions));
8007 switch(cdb->START_STOP.PowerConditions) {
8008 case StartStop_Power_Idle:
8009 command = IDE_COMMAND_IDLE_IMMED;
8010 break;
8011 case StartStop_Power_Standby:
8012 command = IDE_COMMAND_STANDBY_IMMED;
8013 break;
8014 case StartStop_Power_Sleep:
8015 // TODO: we should save power state in order to know
8016 // that RESET sould be issued to revert device into
8017 // operable state
8018
8019 command = IDE_COMMAND_SLEEP;
8020 break;
8021 default:
8022 goto invalid_cdb;
8023 }
8024 LunExt->PowerState = cdb->START_STOP.PowerConditions;
8025 } else
8026 if (cdb->START_STOP.LoadEject == 1) {
8027 KdPrint2((PRINT_PREFIX "START_STOP eject\n"));
8028 // Eject media,
8029 // first select device 0 or 1.
8030 //SelectDrive(chan, DeviceNumber);
8031 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_MEDIA_EJECT);
8032 command = IDE_COMMAND_MEDIA_EJECT;
8033 } else
8034 if (cdb->START_STOP.Start == 0) {
8035 KdPrint2((PRINT_PREFIX "START_STOP standby\n"));
8036 command = IDE_COMMAND_STANDBY_IMMED;
8037 } else {
8038 // TODO: we may need to perform hard reset (after sleep) or
8039 // issue IDE_COMMAND_IDLE_IMMED in order to activate device
8040 KdPrint2((PRINT_PREFIX "START_STOP activate\n"));
8041
8042 if(LunExt->PowerState == StartStop_Power_Sleep) {
8043 UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
8044 status = SRB_STATUS_SUCCESS;
8045 break;
8046 } else
8047 if(LunExt->PowerState > StartStop_Power_Idle) {
8048 KdPrint2((PRINT_PREFIX " issue IDLE\n"));
8049 command = IDE_COMMAND_IDLE_IMMED;
8050 } else {
8051 KdPrint2((PRINT_PREFIX " do nothing\n"));
8052 status = SRB_STATUS_SUCCESS;
8053 break;
8054 }
8055 }
8056 if(command) {
8057 statusByte = WaitOnBaseBusy(chan);
8058 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, command, 0, 0, 0, 0, 0,
8059 cdb->START_STOP.Immediate ? ATA_IMMEDIATE : ATA_WAIT_READY);
8060 status = (statusByte & IDE_STATUS_ERROR) ? SRB_STATUS_ERROR : SRB_STATUS_SUCCESS;
8061 //UniataExpectChannelInterrupt(chan, TRUE); // device may interrupt
8062
8063 } else {
8064 invalid_cdb:
8065 KdPrint2((PRINT_PREFIX "START_STOP invalid\n"));
8066 if (Srb->SenseInfoBuffer) {
8067
8068 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
8069
8070 senseBuffer->ErrorCode = 0x70;
8071 senseBuffer->Valid = 1;
8072 senseBuffer->AdditionalSenseLength = 0xb;
8073 senseBuffer->SenseKey = SCSI_SENSE_ILLEGAL_REQUEST;
8074 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_INVALID_CDB;
8075 senseBuffer->AdditionalSenseCodeQualifier = 0;
8076
8077 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
8078 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
8079 }
8080 status = SRB_STATUS_ERROR;
8081 }
8082 break;
8083
8084 case SCSIOP_MEDIUM_REMOVAL:
8085
8086 cdb = (PCDB)Srb->Cdb;
8087
8088 if(LunExt->IdentifyData.Removable) {
8089 statusByte = WaitOnBaseBusy(chan);
8090
8091 //SelectDrive(chan, DeviceNumber);
8092 if (cdb->MEDIA_REMOVAL.Prevent == TRUE) {
8093 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_LOCK);
8094 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_LOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
8095 } else {
8096 //AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_DOOR_UNLOCK);
8097 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel, IDE_COMMAND_DOOR_UNLOCK, 0, 0, 0, 0, 0, ATA_IMMEDIATE);
8098 }
8099 status = SRB_STATUS_SUCCESS;
8100 } else {
8101 status = SRB_STATUS_INVALID_REQUEST;
8102 }
8103 break;
8104
8105 #if 0
8106 // Note: I don't implement this, because NTFS driver too often issues this command
8107 // It causes awful performance degrade. However, if somebody wants, I will implement
8108 // SCSIOP_FLUSH_BUFFER/SCSIOP_SYNCHRONIZE_CACHE optionally.
8109 case SCSIOP_FLUSH_BUFFER:
8110 case SCSIOP_SYNCHRONIZE_CACHE:
8111
8112 SelectDrive(chan, DeviceNumber);
8113 AtapiWritePort1(chan, IDX_IO1_o_Command,IDE_COMMAND_FLUSH_CACHE);
8114 status = SRB_STATUS_SUCCESS;
8115 // status = SRB_STATUS_PENDING;
8116 statusByte = WaitOnBusy(chan);
8117 break;
8118 #endif
8119
8120 case SCSIOP_REQUEST_SENSE:
8121 // this function makes sense buffers to report the results
8122 // of the original GET_MEDIA_STATUS command
8123
8124 KdPrint2((PRINT_PREFIX
8125 "IdeSendCommand: SCSIOP_REQUEST_SENSE PATH:LUN:TID = %#x:%#x:%#x\n",
8126 Srb->PathId, Srb->Lun, Srb->TargetId));
8127 if (LunExt->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED) {
8128 status = IdeBuildSenseBuffer(HwDeviceExtension,Srb);
8129 break;
8130 }
8131 status = SRB_STATUS_INVALID_REQUEST;
8132 break;
8133
8134 // ATA_PASSTHORUGH
8135 case SCSIOP_ATA_PASSTHROUGH:
8136 {
8137 PIDEREGS_EX regs;
8138 BOOLEAN use_dma = FALSE;
8139 ULONG to_lim;
8140
8141 regs = (PIDEREGS_EX) &(Srb->Cdb[2]);
8142
8143 if(chan->DeviceExtension->HwFlags & UNIATA_SATA) {
8144 //lChannel = Srb->TargetId >> 1;
8145 } else {
8146 DeviceNumber = max(DeviceNumber, 1);
8147 regs->bDriveHeadReg &= 0x0f;
8148 regs->bDriveHeadReg |= (UCHAR) (((DeviceNumber & 0x1) << 4) | 0xA0);
8149 }
8150
8151 if((regs->bOpFlags & 1) == 0) { // execute ATA command
8152
8153 KdPrint2((PRINT_PREFIX
8154 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (exec) PATH:LUN:TID = %#x:%#x:%#x\n",
8155 Srb->PathId, Srb->Lun, Srb->TargetId));
8156
8157 if((regs->bOpFlags & UNIATA_SPTI_EX_SPEC_TO) == UNIATA_SPTI_EX_SPEC_TO) {
8158 to_lim = Srb->TimeOutValue;
8159 } else {
8160 if(Srb->TimeOutValue <= 2) {
8161 to_lim = Srb->TimeOutValue*900;
8162 } else {
8163 to_lim = (Srb->TimeOutValue*999) - 500;
8164 }
8165 }
8166
8167 AtapiDisableInterrupts(deviceExtension, lChannel);
8168
8169 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
8170 // AHCI
8171 statusByte = UniataAhciSendPIOCommandDirect(
8172 deviceExtension,
8173 lChannel,
8174 DeviceNumber,
8175 Srb,
8176 regs,
8177 ATA_WAIT_INTR,
8178 to_lim
8179 );
8180 if(statusByte == IDE_STATUS_WRONG) {
8181 goto passthrough_err;
8182 }
8183 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
8184 UniataAhciAbortOperation(chan);
8185 goto passthrough_err;
8186 }
8187 goto passthrough_done;
8188 }
8189
8190 // SATA/PATA
8191 if((AtaCommandFlags[regs->bCommandReg] & ATA_CMD_FLAG_DMA) || (regs->bOpFlags & UNIATA_SPTI_EX_USE_DMA)) {
8192 if((chan->lun[DeviceNumber]->LimitedTransferMode >= ATA_DMA)) {
8193 use_dma = TRUE;
8194 // this will set REQ_FLAG_DMA_OPERATION in AtaReq->Flags on success
8195 if(!AtapiDmaSetup(HwDeviceExtension, DeviceNumber, lChannel, Srb,
8196 (PUCHAR)(Srb->DataBuffer),
8197 ((Srb->DataTransferLength + DEV_BSIZE-1) & ~(DEV_BSIZE-1)))) {
8198 use_dma = FALSE;
8199 }
8200 }
8201 }
8202
8203 AtapiWritePort1(chan, IDX_IO1_o_DriveSelect, regs->bDriveHeadReg);
8204 AtapiStallExecution(10);
8205
8206 if((regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) == 0) { // execute ATA command
8207 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
8208 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
8209 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
8210 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
8211 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
8212 } else {
8213 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesRegH);
8214 AtapiWritePort1(chan, IDX_IO1_o_Feature, regs->bFeaturesReg);
8215 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountRegH);
8216 AtapiWritePort1(chan, IDX_IO1_o_BlockCount, regs->bSectorCountReg);
8217 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberRegH);
8218 AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, regs->bSectorNumberReg);
8219 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowRegH);
8220 AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, regs->bCylLowReg);
8221 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighRegH);
8222 AtapiWritePort1(chan, IDX_IO1_o_CylinderHigh, regs->bCylHighReg);
8223 }
8224 AtapiWritePort1(chan, IDX_IO1_o_Command, regs->bCommandReg);
8225
8226 if(use_dma) {
8227 GetBaseStatus(chan, statusByte);
8228 if(statusByte & IDE_STATUS_ERROR) {
8229 goto passthrough_err;
8230 }
8231 AtapiDmaStart(HwDeviceExtension, DeviceNumber, lChannel, Srb);
8232 }
8233
8234 ScsiPortStallExecution(1); // wait for busy to be set
8235
8236 for(i=0; i<to_lim;i+=2) { // 2 msec from WaitOnBaseBusy()
8237 statusByte = WaitOnBaseBusy(chan); // wait for busy to be clear, up to 2 msec
8238 GetBaseStatus(chan, statusByte);
8239 if(statusByte & IDE_STATUS_ERROR) {
8240 break;
8241 }
8242 if(!(statusByte & IDE_STATUS_BUSY)) {
8243 break;
8244 }
8245 }
8246 if(i >= to_lim) {
8247 //if(regs->bOpFlags & UNIATA_SPTI_EX_FREEZE_TO) {
8248 //}
8249 AtapiResetController__(HwDeviceExtension, lChannel, RESET_COMPLETE_NONE);
8250 goto passthrough_err;
8251 }
8252
8253 if(use_dma) {
8254 AtapiCheckInterrupt__(deviceExtension, (UCHAR)lChannel);
8255 }
8256 AtapiDmaDone(deviceExtension, DeviceNumber, lChannel, NULL);
8257 GetBaseStatus(chan, statusByte);
8258
8259 if(statusByte & (IDE_STATUS_BUSY | IDE_STATUS_ERROR)) {
8260 AtapiSuckPort2(chan);
8261 passthrough_err:
8262 if (Srb->SenseInfoBuffer) {
8263
8264 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->SenseInfoBuffer;
8265
8266 senseBuffer->ErrorCode = 0x70;
8267 senseBuffer->Valid = 1;
8268 senseBuffer->AdditionalSenseLength = 0xb;
8269 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
8270 senseBuffer->AdditionalSenseCode = 0;
8271 senseBuffer->AdditionalSenseCodeQualifier = 0;
8272
8273 Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID;
8274 Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
8275 }
8276 status = SRB_STATUS_ERROR;
8277 } else {
8278
8279 if(!use_dma) {
8280 if (statusByte & IDE_STATUS_DRQ) {
8281 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
8282 ReadBuffer(chan,
8283 (PUSHORT) Srb->DataBuffer,
8284 Srb->DataTransferLength / 2,
8285 0);
8286 } else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
8287 WriteBuffer(chan,
8288 (PUSHORT) Srb->DataBuffer,
8289 Srb->DataTransferLength / 2,
8290 0);
8291 }
8292 }
8293 }
8294 status = SRB_STATUS_SUCCESS;
8295 }
8296 passthrough_done:;
8297 AtapiEnableInterrupts(deviceExtension, lChannel);
8298
8299 } else { // read task register
8300
8301 BOOLEAN use48;
8302 regs = (PIDEREGS_EX) Srb->DataBuffer;
8303
8304 KdPrint2((PRINT_PREFIX
8305 "IdeSendCommand: SCSIOP_ATA_PASSTHROUGH (snap) PATH:LUN:TID = %#x:%#x:%#x\n",
8306 Srb->PathId, Srb->Lun, Srb->TargetId));
8307
8308 if((Srb->DataTransferLength >= sizeof(IDEREGS_EX)) &&
8309 (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND)) {
8310 use48 = TRUE;
8311 } else
8312 if(Srb->DataTransferLength >= sizeof(IDEREGS)) {
8313 use48 = FALSE;
8314 } else {
8315 KdPrint2((PRINT_PREFIX " buffer too small \n"));
8316 status = SRB_STATUS_DATA_OVERRUN;
8317 break;
8318 }
8319 RtlZeroMemory(regs, use48 ? sizeof(IDEREGS_EX) : sizeof(IDEREGS));
8320 regs->bOpFlags = use48 ? ATA_FLAGS_48BIT_COMMAND : 0;
8321 UniataSnapAtaRegs(chan, 0, regs);
8322
8323 status = SRB_STATUS_SUCCESS;
8324 }
8325 break;
8326 }
8327
8328 default:
8329 default_abort:
8330 KdPrint2((PRINT_PREFIX
8331 "IdeSendCommand: Unsupported command %#x\n",
8332 Srb->Cdb[0]));
8333
8334 status = SRB_STATUS_INVALID_REQUEST;
8335
8336 } // end switch
8337
8338 if(status == SRB_STATUS_PENDING) {
8339 KdPrint2((PRINT_PREFIX "IdeSendCommand: SRB_STATUS_PENDING\n"));
8340 if(CmdAction & CMD_ACTION_EXEC) {
8341 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_EXPECTING_INTR\n"));
8342 AtaReq->ReqState = REQ_STATE_EXPECTING_INTR;
8343 }
8344 } else {
8345 KdPrint2((PRINT_PREFIX "IdeSendCommand: REQ_STATE_TRANSFER_COMPLETE\n"));
8346 AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE;
8347 }
8348
8349 return status;
8350
8351 } // end IdeSendCommand()
8352
8353
8354 /*++
8355
8356 Routine Description:
8357 Enables disables media status notification
8358
8359 Arguments:
8360 HwDeviceExtension - ATAPI driver storage.
8361
8362 --*/
8363 VOID
8364 NTAPI
8365 IdeMediaStatus(
8366 BOOLEAN EnableMSN,
8367 IN PVOID HwDeviceExtension,
8368 IN ULONG lChannel,
8369 IN ULONG DeviceNumber
8370 )
8371 {
8372 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8373 PHW_CHANNEL chan;
8374 UCHAR statusByte,errorByte;
8375
8376 chan = &(deviceExtension->chan[lChannel]);
8377 SelectDrive(chan, DeviceNumber);
8378
8379 if (EnableMSN == TRUE){
8380
8381 // If supported enable Media Status Notification support
8382 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_REMOVABLE_DRIVE)) {
8383
8384 // enable
8385 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8386 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8387 0, ATA_C_F_ENAB_MEDIASTAT, ATA_WAIT_BASE_READY);
8388
8389 if (statusByte & IDE_STATUS_ERROR) {
8390 // Read the error register.
8391 errorByte = AtapiReadPort1(chan, IDX_IO1_i_Error);
8392
8393 KdPrint2((PRINT_PREFIX
8394 "IdeMediaStatus: Error enabling media status. Status %#x, error byte %#x\n",
8395 statusByte,
8396 errorByte));
8397 } else {
8398 chan->lun[DeviceNumber]->DeviceFlags |= DFLAGS_MEDIA_STATUS_ENABLED;
8399 KdPrint2((PRINT_PREFIX "IdeMediaStatus: Media Status Notification Supported\n"));
8400 chan->ReturningMediaStatus = 0;
8401
8402 }
8403
8404 }
8405 } else { // end if EnableMSN == TRUE
8406
8407 // disable if previously enabled
8408 if ((chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_MEDIA_STATUS_ENABLED)) {
8409
8410 statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8411 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8412 0, ATA_C_F_DIS_MEDIASTAT, ATA_WAIT_BASE_READY);
8413 chan->lun[DeviceNumber]->DeviceFlags &= ~DFLAGS_MEDIA_STATUS_ENABLED;
8414 }
8415
8416
8417 }
8418
8419
8420 } // end IdeMediaStatus()
8421
8422
8423 /*++
8424
8425 Routine Description:
8426
8427 Builts an artificial sense buffer to report the results of a GET_MEDIA_STATUS
8428 command. This function is invoked to satisfy the SCSIOP_REQUEST_SENSE.
8429 Arguments:
8430
8431 HwDeviceExtension - ATAPI driver storage.
8432 Srb - System request block.
8433
8434 Return Value:
8435
8436 SRB status (ALWAYS SUCCESS).
8437
8438 --*/
8439 ULONG
8440 NTAPI
8441 IdeBuildSenseBuffer(
8442 IN PVOID HwDeviceExtension,
8443 IN PSCSI_REQUEST_BLOCK Srb
8444 )
8445 {
8446 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8447 // ULONG status;
8448 PSENSE_DATA senseBuffer = (PSENSE_DATA)Srb->DataBuffer;
8449 UCHAR ReturningMediaStatus = deviceExtension->chan[GET_CHANNEL(Srb)].ReturningMediaStatus;
8450
8451 if (senseBuffer){
8452
8453 if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE) {
8454
8455 senseBuffer->ErrorCode = 0x70;
8456 senseBuffer->Valid = 1;
8457 senseBuffer->AdditionalSenseLength = 0xb;
8458 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
8459 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
8460 senseBuffer->AdditionalSenseCodeQualifier = 0;
8461 } else if(ReturningMediaStatus & IDE_ERROR_MEDIA_CHANGE_REQ) {
8462
8463 senseBuffer->ErrorCode = 0x70;
8464 senseBuffer->Valid = 1;
8465 senseBuffer->AdditionalSenseLength = 0xb;
8466 senseBuffer->SenseKey = SCSI_SENSE_UNIT_ATTENTION;
8467 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_MEDIUM_CHANGED;
8468 senseBuffer->AdditionalSenseCodeQualifier = 0;
8469 } else if(ReturningMediaStatus & IDE_ERROR_END_OF_MEDIA) {
8470
8471 senseBuffer->ErrorCode = 0x70;
8472 senseBuffer->Valid = 1;
8473 senseBuffer->AdditionalSenseLength = 0xb;
8474 senseBuffer->SenseKey = SCSI_SENSE_NOT_READY;
8475 senseBuffer->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
8476 senseBuffer->AdditionalSenseCodeQualifier = 0;
8477 } else if(ReturningMediaStatus & IDE_ERROR_DATA_ERROR) {
8478
8479 senseBuffer->ErrorCode = 0x70;
8480 senseBuffer->Valid = 1;
8481 senseBuffer->AdditionalSenseLength = 0xb;
8482 senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT;
8483 senseBuffer->AdditionalSenseCode = 0;
8484 senseBuffer->AdditionalSenseCodeQualifier = 0;
8485 }
8486 return SRB_STATUS_SUCCESS;
8487 }
8488 return SRB_STATUS_ERROR;
8489
8490 }// End of IdeBuildSenseBuffer
8491
8492 VOID
8493 NTAPI
8494 UniataUserDeviceReset(
8495 PHW_DEVICE_EXTENSION deviceExtension,
8496 PHW_LU_EXTENSION LunExt,
8497 ULONG lChannel
8498 )
8499 {
8500 ULONG i;
8501 AtapiDisableInterrupts(deviceExtension, lChannel);
8502 if ((LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) &&
8503 (LunExt->PowerState != StartStop_Power_Sleep)) {
8504 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset ATAPI\n"));
8505 AtapiSoftReset(&(deviceExtension->chan[lChannel]), LunExt->Lun);
8506 } else {
8507 KdPrint2((PRINT_PREFIX "UniataUserDeviceReset: Reset IDE -> reset entire channel\n"));
8508 AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_NONE);
8509 for(i=0; i<deviceExtension->NumberLuns; i++) {
8510 deviceExtension->chan[lChannel].lun[i]->DeviceFlags |= DFLAGS_REINIT_DMA;
8511 }
8512 }
8513 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
8514 AtapiEnableInterrupts(deviceExtension, lChannel);
8515 return;
8516 } // end UniataUserDeviceReset()
8517
8518 BOOLEAN
8519 NTAPI
8520 UniataNeedQueueing(
8521 PHW_DEVICE_EXTENSION deviceExtension,
8522 PHW_CHANNEL chan,
8523 BOOLEAN TopLevel
8524 )
8525 {
8526 BOOLEAN PostReq = FALSE;
8527 if(TopLevel) {
8528 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: TopLevel, qd=%x\n", chan->queue_depth));
8529 if(chan->queue_depth > 0) {
8530 #if 0
8531 if(atapiDev &&
8532 ((Srb->Cdb[0] == SCSIOP_TEST_UNIT_READY)/* ||
8533 (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)*/) ) {
8534 KdPrint2((PRINT_PREFIX "spec: SCSIOP_TEST_UNIT_READY\n"));
8535 //PostReq = FALSE;
8536 status = SRB_STATUS_BUSY;
8537 goto skip_exec;
8538 } else {
8539 PostReq = TRUE;
8540 }
8541 #else
8542 PostReq = TRUE;
8543 #endif
8544 } else
8545 if(deviceExtension->simplexOnly && deviceExtension->queue_depth > 0) {
8546 PostReq = TRUE;
8547 }
8548 } else {
8549 KdPrint3((PRINT_PREFIX "UniataNeedQueueing: qd=%x\n", chan->queue_depth));
8550 }
8551 return PostReq;
8552 } // end UniataNeedQueueing()
8553
8554 /*++
8555
8556 Routine Description:
8557
8558 This routine is called from the SCSI port driver synchronized
8559 with the kernel to start an IO request.
8560 ->HwStartIo
8561
8562 Arguments:
8563
8564 HwDeviceExtension - HBA miniport driver's adapter data storage
8565 Srb - IO request packet
8566
8567 Return Value:
8568
8569 TRUE
8570
8571 --*/
8572 BOOLEAN
8573 NTAPI
8574 AtapiStartIo(
8575 IN PVOID HwDeviceExtension,
8576 IN PSCSI_REQUEST_BLOCK Srb
8577 )
8578 {
8579 return AtapiStartIo__(HwDeviceExtension, Srb, TRUE);
8580 } // end AtapiStartIo()
8581
8582 BOOLEAN
8583 NTAPI
8584 AtapiStartIo__(
8585 IN PVOID HwDeviceExtension,
8586 IN PSCSI_REQUEST_BLOCK Srb,
8587 IN BOOLEAN TopLevel
8588 )
8589 {
8590 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
8591 UCHAR lChannel;
8592 PHW_CHANNEL chan;
8593 PHW_LU_EXTENSION LunExt;
8594 ULONG status;
8595 //ULONG ldev;
8596 ULONG DeviceNumber;
8597 UCHAR PathId;
8598 UCHAR TargetId;
8599 UCHAR Lun;
8600 PATA_REQ AtaReq;
8601 PSCSI_REQUEST_BLOCK tmpSrb;
8602 BOOLEAN PostReq = FALSE;
8603 BOOLEAN atapiDev;
8604 BOOLEAN commPort = FALSE;
8605
8606 // deviceExtension->Isr2DevObj must always be NULL for non-PCI
8607 if(deviceExtension->Isr2DevObj && !BMList[deviceExtension->DevIndex].Isr2Enable) {
8608 KdPrint2((PRINT_PREFIX "Isr2Enable -> 1\n"));
8609 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
8610 }
8611 // deviceExtension->QueueNewIrql = max(deviceExtension->QueueNewIrql, KeGetCurrentIrql());
8612
8613 /* KeBugCheckEx(0xc000000e,
8614 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8615 Srb->Function,
8616 TopLevel, 0x80000001);
8617 */
8618 if(TopLevel && Srb && Srb->SrbExtension) {
8619 KdPrint2((PRINT_PREFIX "TopLevel\n"));
8620 //RtlZeroMemory(Srb->SrbExtension, sizeof(ATA_REQ));
8621 UniAtaClearAtaReq(Srb->SrbExtension);
8622 }
8623
8624 do { // fetch all queued commands for the channel (if valid)
8625
8626 lChannel = GET_CHANNEL(Srb);
8627 //ldev = GET_LDEV(Srb);
8628 chan = NULL;
8629 LunExt = NULL;
8630 DeviceNumber = GET_CDEV(Srb);
8631 commPort = FALSE;
8632
8633 //ASSERT(deviceExtension);
8634 //ASSERT(chan);
8635
8636 KdPrint2((PRINT_PREFIX
8637 "** AtapiStartIo: Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8638 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId));
8639 KdPrint2((PRINT_PREFIX " VendorID+DeviceID/Rev %#x/%#x\n", deviceExtension->DevID, deviceExtension->RevID));
8640
8641 if(lChannel == deviceExtension->NumberChannels &&
8642 !Srb->Lun && !Srb->TargetId &&
8643 ((Srb->Function == SRB_FUNCTION_IO_CONTROL) ||
8644 (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI && Srb->Cdb[0] == SCSIOP_INQUIRY))
8645 ) {
8646 // This is our virtual device
8647 KdPrint2((PRINT_PREFIX
8648 "AtapiStartIo: Communication port\n"));
8649 if(Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) {
8650
8651 if(Srb->DataTransferLength < sizeof(PINQUIRYDATA)) {
8652 KdPrint2((PRINT_PREFIX "AtapiStartIo: Buffer too small: %#x < %#x\n", Srb->DataTransferLength,
8653 sizeof(PINQUIRYDATA) ));
8654 wrong_buffer_size:
8655 status = SRB_STATUS_DATA_OVERRUN;
8656 goto complete_req;
8657 }
8658
8659 PINQUIRYDATA inquiryData = (PINQUIRYDATA)(Srb->DataBuffer);
8660
8661 KdPrint2((PRINT_PREFIX
8662 " INQUIRY\n"));
8663 // Zero INQUIRY data structure.
8664 RtlZeroMemory((PCHAR)(Srb->DataBuffer), Srb->DataTransferLength);
8665
8666 inquiryData->DeviceType = COMMUNICATION_DEVICE;
8667
8668 // Fill in vendor identification fields.
8669 RtlCopyMemory(&inquiryData->VendorId, &uniata_comm_name, 28);
8670
8671 status = SRB_STATUS_SUCCESS;
8672 goto complete_req;
8673 }
8674 commPort = TRUE;
8675 /* Pass IOCTL request down */
8676 } else
8677 if(lChannel >= deviceExtension->NumberChannels ||
8678 Srb->TargetId /*DeviceNumber*/ >= deviceExtension->NumberLuns ||
8679 Srb->Lun) {
8680
8681 if(lChannel >= deviceExtension->NumberChannels) {
8682 chan = NULL;
8683 }
8684
8685 reject_srb:
8686 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8687 KdPrint3((PRINT_PREFIX
8688 "AtapiStartIo: SRB rejected\n"));
8689 // Indicate no device found at this address.
8690 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
8691 status = SRB_STATUS_SELECTION_TIMEOUT;
8692 goto complete_req;
8693 //}
8694 } else
8695 if((deviceExtension->HwFlags & UNIATA_AHCI) &&
8696 !UniataAhciChanImplemented(deviceExtension, lChannel)) {
8697 chan = NULL;
8698 }
8699
8700 if(!commPort) {
8701 chan = &(deviceExtension->chan[lChannel]);
8702 LunExt = chan->lun[DeviceNumber];
8703 if(!LunExt) {
8704 goto reject_srb;
8705 }
8706 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
8707 } else {
8708 atapiDev = FALSE;
8709 }
8710
8711 #ifdef _DEBUG
8712 if(!commPort && !LunExt) {
8713 #if 0
8714 PrintNtConsole("de = %#x, chan = %#x , dev %#x, nchan %#x\n",
8715 deviceExtension,
8716 chan, DeviceNumber,
8717 deviceExtension->NumberChannels);
8718 PrintNtConsole("lchan = %#x, cdev %#x, lun0 %#x\n",
8719 lChannel, GET_CDEV(Srb), deviceExtension->chan[0].lun[0]);
8720 PrintNtConsole("Function %#x, PATH:LUN:TID = %#x:%#x:%#x\n",
8721 Srb->Function, Srb->PathId, Srb->Lun, Srb->TargetId);
8722 #endif //0
8723 /*
8724 int i;
8725 for(i=0; i<1000; i++) {
8726 AtapiStallExecution(3*1000);
8727 }
8728 */
8729 goto reject_srb;
8730 }
8731 #endif //_DEBUG
8732
8733 // Determine which function.
8734 switch (Srb->Function) {
8735
8736 case SRB_FUNCTION_EXECUTE_SCSI:
8737
8738 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8739 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
8740 // let passthrough go
8741 } else
8742 if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
8743 // let INQUIRY go
8744 } else {
8745
8746 //if(!CheckDevice(HwDeviceExtension, lChannel, DeviceNumber, FALSE)) {
8747 KdPrint2((PRINT_PREFIX
8748 "AtapiStartIo: EXECUTE_SCSI rejected (2)\n"));
8749 // Indicate no device found at this address.
8750 KdPrint2((PRINT_PREFIX "SRB_STATUS_SELECTION_TIMEOUT\n"));
8751 status = SRB_STATUS_SELECTION_TIMEOUT;
8752 break;
8753 //}
8754 }
8755 } else {
8756 KdPrint2((PRINT_PREFIX
8757 " SRB %#x, CDB %#x, AtaReq %#x, SCmd %#x\n", Srb, &(Srb->Cdb), Srb->SrbExtension, Srb->Cdb[0]));
8758 }
8759 /*
8760 __try {
8761 if(Srb->DataTransferLength) {
8762 UCHAR a;
8763 a = ((PUCHAR)(Srb->DataBuffer))[0];
8764 g_foo += a;
8765 }
8766 } __except(EXCEPTION_EXECUTE_HANDLER) {
8767 KdPrint3((PRINT_PREFIX
8768 "AtapiStartIo: Bad data buffer -> EXECUTE_SCSI rejected\n"));
8769 // Indicate no device found at this address.
8770 KdPrint3((PRINT_PREFIX "SRB_STATUS_ERROR\n"));
8771 status = SRB_STATUS_ERROR;
8772 KdPrint2((PRINT_PREFIX " *** Exception...\n"));
8773 ASSERT(FALSE);
8774 break;
8775 }
8776 */
8777 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
8778
8779 if(PostReq) {
8780
8781 KdPrint3((PRINT_PREFIX "Non-empty queue\n"));
8782 if (atapiDev &&
8783 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)) {
8784 KdPrint3((PRINT_PREFIX "Try ATAPI prepare\n"));
8785
8786 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
8787 } else {
8788 KdPrint2((PRINT_PREFIX "Try IDE prepare\n"));
8789 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_PREPARE);
8790 }
8791 /*KeBugCheckEx(0xc000000e,
8792 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8793 Srb->Function,
8794 status, 0x80000001);*/
8795 if(status == SRB_STATUS_BUSY)
8796 status = SRB_STATUS_PENDING;
8797 // Insert requests AFTER they have been initialized on
8798 // CMD_ACTION_PREPARE stage
8799 // we should not check TopLevel here (it is always TRUE)
8800 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8801 UniataQueueRequest(chan, Srb);
8802
8803 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
8804
8805 } else {
8806
8807 // Send command to device.
8808 KdPrint2((PRINT_PREFIX "Send to device %x\n", Srb->Cdb[0]));
8809 if(TopLevel) {
8810 KdPrint2((PRINT_PREFIX "TopLevel (2), srb %#x\n", Srb));
8811 AtaReq = (PATA_REQ)(Srb->SrbExtension);
8812 KdPrint2((PRINT_PREFIX "TopLevel (3), AtaReq %#x\n", AtaReq));
8813 //ASSERT(!AtaReq->Flags);
8814 //ASSERT(chan->lun[GET_CDEV(Srb)]);
8815 UniataQueueRequest(chan, Srb);
8816 // AtaReq = (PATA_REQ)(Srb->SrbExtension);
8817 //ASSERT(!AtaReq->Flags);
8818 AtaReq->ReqState = REQ_STATE_QUEUED;
8819 //ASSERT(!AtaReq->Flags);
8820 }
8821
8822 #ifndef NAVO_TEST
8823 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8824 if(!LunExt) {
8825 goto reject_srb;
8826 }
8827 if(Srb->Cdb[0] == SCSIOP_INQUIRY) {
8828 if(UniataAnybodyHome(deviceExtension, chan->lChannel, DeviceNumber)) {
8829 if(!CheckDevice(HwDeviceExtension, chan->lChannel, DeviceNumber, TRUE)) {
8830 goto reject_srb;
8831 }
8832 }
8833 if(!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8834 goto reject_srb;
8835 }
8836 } else
8837 if(Srb->Cdb[0] == SCSIOP_ATA_PASSTHROUGH) {
8838 // allow
8839 } else {
8840 goto reject_srb;
8841 }
8842 }
8843 #endif //NAVO_TEST
8844
8845 if(atapiDev &&
8846 (Srb->Cdb[0] != SCSIOP_ATA_PASSTHROUGH)/* &&
8847 (Srb->Cdb[0] != SCSIOP_REPORT_LUNS)*/) {
8848 KdPrint3((PRINT_PREFIX "Try ATAPI send %x\n", Srb->Cdb[0]));
8849 status = AtapiSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
8850 } else {
8851 KdPrint2((PRINT_PREFIX "Try IDE send\n"));
8852 /* {
8853 ULONG __ebp__ = 0;
8854 ULONG __esp__ = 0;
8855
8856 KdPrint2((PRINT_PREFIX "** before IdeSendCommand:\n"));
8857 __asm {
8858 mov eax,ebp
8859 mov __ebp__, eax
8860 mov eax,esp
8861 mov __esp__, eax
8862 }
8863 KdPrint2((PRINT_PREFIX "** before Ide: EBP:%#x ESP:%#x\n", __ebp__, __esp__));
8864 }*/
8865 status = IdeSendCommand(HwDeviceExtension, Srb, CMD_ACTION_ALL);
8866 }
8867 /* KeBugCheckEx(0xc000000e,
8868 (Srb->PathId<<16) | (Srb->TargetId<<8) | (Srb->Lun),
8869 Srb->Function,
8870 status, 0x80000002);*/
8871
8872 }
8873 //skip_exec:
8874 TopLevel = FALSE;
8875
8876 break;
8877
8878 case SRB_FUNCTION_ABORT_COMMAND:
8879
8880 tmpSrb = ScsiPortGetSrb(HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun,
8881 Srb->QueueTag);
8882 // Verify that SRB to abort is still outstanding.
8883 if((tmpSrb != Srb->NextSrb) ||
8884 !chan->queue_depth) {
8885
8886 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB to abort already completed\n"));
8887
8888 // Complete abort SRB.
8889 status = SRB_STATUS_ABORT_FAILED;
8890 break;
8891 }
8892
8893 AtaReq = (PATA_REQ)(tmpSrb->SrbExtension);
8894 if(AtaReq->ReqState > REQ_STATE_READY_TO_TRANSFER) {
8895 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_CURRENT)) {
8896 KdPrint2((PRINT_PREFIX "AtapiStartIo: Abort command failed\n"));
8897 // Log reset failure.
8898 KdPrint3((PRINT_PREFIX
8899 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d)\n",
8900 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
8901 ));
8902 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
8903 status = SRB_STATUS_ERROR;
8904
8905 } else {
8906 status = SRB_STATUS_SUCCESS;
8907 }
8908 } else {
8909 KdPrint2((PRINT_PREFIX "AtapiInterrupt: remove aborted srb %#x\n", tmpSrb));
8910 if (tmpSrb->SenseInfoBuffer &&
8911 tmpSrb->SenseInfoBufferLength >= sizeof(SENSE_DATA)) {
8912
8913 PSENSE_DATA senseBuffer = (PSENSE_DATA)tmpSrb->SenseInfoBuffer;
8914
8915 senseBuffer->ErrorCode = 0;
8916 senseBuffer->Valid = 1;
8917 senseBuffer->AdditionalSenseLength = 0xb;
8918 senseBuffer->SenseKey = SCSI_SENSE_ABORTED_COMMAND;
8919 senseBuffer->AdditionalSenseCode = 0;
8920 senseBuffer->AdditionalSenseCodeQualifier = 0;
8921
8922 tmpSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
8923 }
8924 AtapiDmaDBSync(chan, tmpSrb);
8925 UniataRemoveRequest(chan, tmpSrb);
8926 // Indicate command complete.
8927 ScsiPortNotification(RequestComplete,
8928 deviceExtension,
8929 tmpSrb);
8930 status = SRB_STATUS_SUCCESS;
8931 }
8932 break;
8933
8934 // Abort function indicates that a request timed out.
8935 // Call reset routine. Card will only be reset if
8936 // status indicates something is wrong.
8937 // Fall through to reset code.
8938
8939 case SRB_FUNCTION_RESET_DEVICE:
8940 case SRB_FUNCTION_RESET_LOGICAL_UNIT:
8941
8942 // Reset single device.
8943 // For now we support only Lun=0
8944
8945 // Note: reset is immediate command, it cannot be queued since it is usually used to
8946 // revert not-responding device to operational state
8947 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device request received\n"));
8948 UniataUserDeviceReset(deviceExtension, LunExt, lChannel);
8949 status = SRB_STATUS_SUCCESS;
8950 break;
8951
8952 case SRB_FUNCTION_RESET_BUS:
8953 do_bus_reset:
8954 // Reset Atapi and SCSI bus.
8955
8956 // Note: reset is immediate command, it cannot be queued since it is usually used to
8957 // revert not- responding device to operational state
8958 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus request received\n"));
8959 if (!AtapiResetController__(deviceExtension, lChannel, RESET_COMPLETE_ALL)) {
8960 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset bus failed\n"));
8961 // Log reset failure.
8962 KdPrint3((PRINT_PREFIX
8963 "ScsiPortLogError: devExt %#x, Srb %#x, P:T:D=%d:%d:%d, MsgId %#x (%d) - (2)\n",
8964 HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8
8965 ));
8966 ScsiPortLogError(HwDeviceExtension, NULL, 0, 0, 0, SP_INTERNAL_ADAPTER_ERROR, 5 << 8);
8967 status = SRB_STATUS_ERROR;
8968
8969 } else {
8970 status = SRB_STATUS_SUCCESS;
8971 }
8972
8973 break;
8974
8975 case SRB_FUNCTION_SHUTDOWN:
8976
8977 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown\n"));
8978 if(!LunExt || !(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
8979 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - no such device\n"));
8980 } else
8981 if(atapiDev) {
8982 // FLUSH ATAPI device - do nothing
8983 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - ATAPI device\n"));
8984 } else {
8985 // FLUSH IDE/ATA device
8986 KdPrint2((PRINT_PREFIX "AtapiStartIo: Shutdown - IDE device\n"));
8987 AtapiDisableInterrupts(deviceExtension, lChannel);
8988 status = AtaCommand(deviceExtension, DeviceNumber, GET_CHANNEL(Srb),
8989 IDE_COMMAND_FLUSH_CACHE, 0, 0, 0, 0, 0, ATA_WAIT_IDLE);
8990 // If supported & allowed, reset write cacheing
8991 if(LunExt->DeviceFlags & DFLAGS_WCACHE_ENABLED) {
8992
8993 // Disable write cache
8994 status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
8995 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
8996 0, ATA_C_F_DIS_WCACHE, ATA_WAIT_BASE_READY);
8997 // Check for errors.
8998 if (status & IDE_STATUS_ERROR) {
8999 KdPrint2((PRINT_PREFIX
9000 "AtapiHwInitialize: Disable write cacheing on Device %d failed\n",
9001 DeviceNumber));
9002 }
9003 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
9004
9005 // Re-enable write cache
9006 status = AtaCommand(deviceExtension, DeviceNumber, lChannel,
9007 IDE_COMMAND_SET_FEATURES, 0, 0, 0,
9008 0, ATA_C_F_ENAB_WCACHE, ATA_WAIT_BASE_READY);
9009 // Check for errors.
9010 if (status & IDE_STATUS_ERROR) {
9011 KdPrint2((PRINT_PREFIX
9012 "AtapiHwInitialize: Enable write cacheing on Device %d failed\n",
9013 DeviceNumber));
9014 LunExt->DeviceFlags &= ~DFLAGS_WCACHE_ENABLED;
9015 } else {
9016 LunExt->DeviceFlags |= DFLAGS_WCACHE_ENABLED;
9017 }
9018 }
9019
9020 AtapiEnableInterrupts(deviceExtension, lChannel);
9021 }
9022 status = SRB_STATUS_SUCCESS;
9023
9024 break;
9025
9026 case SRB_FUNCTION_FLUSH:
9027
9028 KdPrint2((PRINT_PREFIX "AtapiStartIo: Flush (do nothing)\n"));
9029 status = SRB_STATUS_SUCCESS;
9030 break;
9031
9032 case SRB_FUNCTION_IO_CONTROL: {
9033
9034 ULONG len;
9035
9036 KdPrint2((PRINT_PREFIX "AtapiStartIo: SRB_FUNCTION_IO_CONTROL\n"));
9037
9038 len = Srb->DataTransferLength;
9039
9040 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"SCSIDISK",sizeof("SCSIDISK")-1)) {
9041
9042 ULONG targetId = (ULONG)(-1);
9043
9044 if(len < sizeof(SRB_IO_CONTROL)) {
9045 goto wrong_buffer_size;
9046 }
9047
9048 // extract bogus bus address
9049 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
9050 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
9051 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9052
9053 if(len < sizeof(SRB_IO_CONTROL)+sizeof(GETVERSIONINPARAMS)) {
9054 goto wrong_buffer_size;
9055 }
9056
9057 targetId = versionParameters->bIDEDeviceMap;
9058 KdPrint2((PRINT_PREFIX "targetId (smart ver) %d\n", targetId));
9059 break; }
9060 case IOCTL_SCSI_MINIPORT_IDENTIFY:
9061 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9062 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9063 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9064 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9065 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9066 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9067 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9068 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9069 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE:
9070 case IOCTL_SCSI_MINIPORT_READ_SMART_LOG:
9071 case IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG:
9072 {
9073 PSENDCMDINPARAMS cmdInParameters = (PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9074
9075 if(len < sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS) - 1) {
9076 goto wrong_buffer_size;
9077 }
9078
9079 targetId = cmdInParameters->bDriveNumber;
9080 KdPrint2((PRINT_PREFIX "targetId (smart/ident) %d\n", targetId));
9081 break; }
9082 default:
9083 invalid_request:
9084 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9085 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9086 status = SRB_STATUS_INVALID_REQUEST;
9087 goto complete_req;
9088 } // end switch()
9089
9090 // adjust (if necessary) bus address
9091 if(targetId != (ULONG)(-1)) {
9092
9093 // This is done because of how the IOCTL_SCSI_MINIPORT
9094 // determines 'targetid's'. Disk.sys places the real target id value
9095 // in the DeviceMap field. Once we do some parameter checking, the value passed
9096 // back to the application will be determined.
9097
9098 if (deviceExtension->NumberChannels == 1) {
9099 // do this for legacy controllers and legacy callers
9100 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call\n"));
9101 DeviceNumber = (targetId & 0x01);
9102 lChannel = 0;
9103 } else
9104 if(commPort) {
9105 // do this for smartmontools, sending IOCTLs to PhysicalDrive%d
9106 // due to DISK.SYS design bug, we have invalid SCSI address in SRB
9107 KdPrint2((PRINT_PREFIX "AtapiStartIo: legacy call (2)\n"));
9108 if(deviceExtension->HwFlags & UNIATA_AHCI) {
9109 lChannel = (UCHAR)targetId / 2;
9110 DeviceNumber = 0;
9111 } else {
9112 lChannel = (UCHAR)(targetId / 2);
9113 DeviceNumber = targetId & 0x01;
9114 }
9115 } else {
9116 // otherwise assume lChannel and DeviceNumber from Srb are ok
9117 }
9118 if(lChannel >= deviceExtension->NumberChannels ||
9119 DeviceNumber >= deviceExtension->NumberLuns) {
9120 KdPrint2((PRINT_PREFIX
9121 "AtapiStartIo: SCSIDISK IOCTL for non-exestent drive %d -> EXECUTE_SCSI rejected (2)\n",
9122 targetId));
9123 // Indicate no device found at this address.
9124 goto reject_srb;
9125 }
9126 targetId = lChannel*deviceExtension->NumberLuns+DeviceNumber;
9127 chan = &(deviceExtension->chan[lChannel]);
9128 LunExt = chan->lun[DeviceNumber];
9129 if(!LunExt) {
9130 goto reject_srb;
9131 }
9132 atapiDev = (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) ? TRUE : FALSE;
9133
9134 if (!(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT)) {
9135 goto reject_srb;
9136 }
9137 }
9138
9139 switch (((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode) {
9140 case IOCTL_SCSI_MINIPORT_SMART_VERSION: {
9141
9142 PGETVERSIONINPARAMS versionParameters = (PGETVERSIONINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9143 UCHAR deviceNumberMap;
9144
9145 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_SMART_VERSION\n"));
9146
9147 // Version and revision per SMART 1.03
9148
9149 versionParameters->bVersion = 1;
9150 versionParameters->bRevision = 1;
9151 versionParameters->bReserved = 0;
9152
9153 // Indicate that support for IDE IDENTIFY, ATAPI IDENTIFY and SMART commands.
9154 versionParameters->fCapabilities = (CAP_ATA_ID_CMD | CAP_ATAPI_ID_CMD | CAP_SMART_CMD);
9155
9156 if (atapiDev) {
9157 goto invalid_request;
9158 }
9159
9160 // NOTE: This will only set the bit
9161 // corresponding to this drive's target id.
9162 // The bit mask is as follows:
9163 //
9164 // -Sec Pri
9165 // S M S M
9166 // 3 2 1 0
9167
9168 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
9169 deviceNumberMap = 1 << lChannel;
9170 DeviceNumber = 0;
9171 } else
9172 if (deviceExtension->NumberChannels == 1) {
9173 if (chan->PrimaryAddress) {
9174 deviceNumberMap = 1 << DeviceNumber;
9175 } else {
9176 deviceNumberMap = 4 << DeviceNumber;
9177 }
9178 } else {
9179 deviceNumberMap = 1 << (DeviceNumber+lChannel*2);
9180 }
9181
9182 versionParameters->bIDEDeviceMap = deviceNumberMap;
9183
9184 status = SRB_STATUS_SUCCESS;
9185 break;
9186 }
9187
9188 case IOCTL_SCSI_MINIPORT_IDENTIFY: {
9189
9190 PSENDCMDOUTPARAMS cmdOutParameters = (PSENDCMDOUTPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9191 SENDCMDINPARAMS cmdInParameters = *(PSENDCMDINPARAMS)(((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL));
9192
9193 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY\n"));
9194 // Extract the target.
9195 KdPrint2((PRINT_PREFIX "targetId %d\n", targetId));
9196
9197 switch(cmdInParameters.irDriveRegs.bCommandReg) {
9198 case ID_CMD:
9199 if(atapiDev) {
9200 KdPrint2((PRINT_PREFIX "Error: ID_CMD for ATAPI\n"));
9201 goto invalid_request;
9202 }
9203 /* FALL THROUGH */
9204 case ATAPI_ID_CMD:
9205
9206 if(!atapiDev &&
9207 (cmdInParameters.irDriveRegs.bCommandReg == ATAPI_ID_CMD)) {
9208 KdPrint2((PRINT_PREFIX "Error: ATAPI_ID_CMD for non-ATAPI\n"));
9209 goto invalid_request;
9210 }
9211
9212 len = min(len, sizeof(SENDCMDOUTPARAMS) - 1 + IDENTIFY_BUFFER_SIZE);
9213 // Zero the output buffer
9214 RtlZeroMemory(cmdOutParameters, len);
9215 /* for (i = 0; i < (sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1); i++) {
9216 ((PUCHAR)cmdOutParameters)[i] = 0;
9217 }*/
9218
9219 // Build status block.
9220 cmdOutParameters->cBufferSize = min(IDENTIFY_BUFFER_SIZE, len - sizeof(SENDCMDOUTPARAMS) + 1);
9221 cmdOutParameters->DriverStatus.bDriverError = 0;
9222 cmdOutParameters->DriverStatus.bIDEError = 0;
9223
9224 // Extract the identify data from the device extension.
9225 ScsiPortMoveMemory (cmdOutParameters->bBuffer, &(LunExt->IdentifyData),
9226 cmdOutParameters->cBufferSize);
9227
9228 if((cmdOutParameters->cBufferSize == IDENTIFY_BUFFER_SIZE) &&
9229 (LunExt->IdentifyData.ChecksumValid == ATA_ChecksumValid)) {
9230 // adjust checksum if it is possible
9231 CHAR csum = 0;
9232 ULONG i;
9233
9234 for(i=0; i < IDENTIFY_BUFFER_SIZE-1; i++) {
9235 csum += (CHAR)(cmdOutParameters->bBuffer[i]);
9236 }
9237 cmdOutParameters->bBuffer[i] = -csum;
9238 KdPrint2((PRINT_PREFIX "AtapiStartIo: adjust checksum %d\n"));
9239 }
9240 KdPrint2((PRINT_PREFIX "AtapiStartIo: IOCTL_SCSI_MINIPORT_IDENTIFY Ok\n"));
9241
9242 status = SRB_STATUS_SUCCESS;
9243
9244 break;
9245 default:
9246 KdPrint2((PRINT_PREFIX "AtapiStartIo: not supported ID code %x\n",
9247 cmdInParameters.irDriveRegs.bCommandReg));
9248 status = SRB_STATUS_INVALID_REQUEST;
9249 break;
9250 }
9251 break;
9252 }
9253 /*
9254 case IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS:
9255 case IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS:
9256 case IOCTL_SCSI_MINIPORT_ENABLE_SMART:
9257 case IOCTL_SCSI_MINIPORT_DISABLE_SMART:
9258 case IOCTL_SCSI_MINIPORT_RETURN_STATUS:
9259 case IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE:
9260 case IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES:
9261 case IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS:
9262 */
9263 default:
9264 // *all* IOCTLs here are SMART
9265 if(commPort) {
9266 KdPrint2((PRINT_PREFIX
9267 "AtapiStartIo: SCSIDISK Smart IOCTL for commPort -> EXECUTE_SCSI rejected (3)\n"));
9268 }
9269 if (atapiDev) {
9270 goto invalid_request;
9271 }
9272
9273 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
9274
9275 if(PostReq || TopLevel) {
9276 UniataQueueRequest(chan, Srb);
9277 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9278 AtaReq->ReqState = REQ_STATE_QUEUED;
9279 }
9280
9281 if(PostReq) {
9282
9283 KdPrint2((PRINT_PREFIX "Non-empty queue (SMART)\n"));
9284 status = SRB_STATUS_PENDING;
9285
9286 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
9287 } else {
9288
9289 status = IdeSendSmartCommand(HwDeviceExtension, Srb, targetId);
9290 }
9291 break;
9292
9293 // we should not get here, checked above
9294 /* default :
9295 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for SCSIDISK signature\n",
9296 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->ControlCode ));
9297 status = SRB_STATUS_INVALID_REQUEST;
9298 break;
9299 */
9300 }
9301 } else
9302 if(!AtapiStringCmp( (PCHAR)(((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature),"-UNIATA-", sizeof("-UNIATA-")-1)) {
9303
9304 PUNIATA_CTL AtaCtl = (PUNIATA_CTL)(Srb->DataBuffer);
9305 //ULONG ldev = GET_LDEV2(AtaCtl->addr.PathId, AtaCtl->addr.TargetId, 0);
9306 ULONG DeviceNumber = AtaCtl->addr.TargetId;
9307 BOOLEAN bad_ldev;
9308 ULONG i, pos;
9309
9310 pos = FIELD_OFFSET(UNIATA_CTL, RawData);
9311 //chan = &(deviceExtension->chan[lChannel]);
9312 if(len < pos) {
9313 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9314 FIELD_OFFSET(UNIATA_CTL, RawData) ));
9315 goto wrong_buffer_size;
9316 }
9317
9318 if(AtaCtl->addr.Lun ||
9319 AtaCtl->addr.TargetId >= deviceExtension->NumberLuns ||
9320 AtaCtl->addr.PathId >= deviceExtension->NumberChannels) {
9321
9322 chan = NULL;
9323 bad_ldev = TRUE;
9324 LunExt = NULL;
9325
9326 } else {
9327 bad_ldev = FALSE;
9328 lChannel = AtaCtl->addr.PathId;
9329 chan = &(deviceExtension->chan[lChannel]);
9330 LunExt = chan->lun[DeviceNumber];
9331 }
9332
9333 KdPrint2((PRINT_PREFIX "AtapiStartIo: -UNIATA- %#x, dev %#x\n", AtaCtl->hdr.ControlCode, DeviceNumber));
9334
9335 /* check for valid LUN */
9336 switch (AtaCtl->hdr.ControlCode) {
9337 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9338 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE:
9339 // this would be BUS reset
9340 if(bad_ldev &&
9341 (AtaCtl->addr.PathId >= deviceExtension->NumberChannels ||
9342 AtaCtl->addr.TargetId != 0xff ||
9343 AtaCtl->addr.Lun != 0
9344 )) {
9345 if(AtaCtl->hdr.ControlCode == IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES &&
9346 DeviceNumber < deviceExtension->NumberLuns) { // AtaCtl->addr.TargetId != 0xff
9347 lChannel = AtaCtl->addr.PathId;
9348 chan = &(deviceExtension->chan[lChannel]);
9349 LunExt = chan->lun[DeviceNumber];
9350 // OK
9351 } else {
9352 goto handle_bad_ldev;
9353 }
9354 } else {
9355 lChannel = AtaCtl->addr.PathId;
9356 chan = &(deviceExtension->chan[lChannel]);
9357 }
9358 break;
9359 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE:
9360 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
9361 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE:
9362 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
9363 // case IOCTL_SCSI_MINIPORT_UNIATA_REG_IO:
9364 if(bad_ldev) {
9365 handle_bad_ldev:
9366 KdPrint2((PRINT_PREFIX
9367 "AtapiStartIo: bad_ldev -> IOCTL SRB rejected\n"));
9368 // Indicate no device found at this address.
9369 goto reject_srb;
9370 }
9371 }
9372
9373 /* check if queueing is necessary */
9374 switch (AtaCtl->hdr.ControlCode) {
9375 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB:
9376 if(!LunExt->nBadBlocks) {
9377 break;
9378 }
9379 goto uata_ctl_queue;
9380 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE:
9381 if(len < pos+sizeof(AtaCtl->SetMode)) {
9382 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9383 pos+sizeof(AtaCtl->SetMode) ));
9384 goto wrong_buffer_size;
9385 }
9386 if(!AtaCtl->SetMode.ApplyImmediately) {
9387 break;
9388 }
9389 goto uata_ctl_queue;
9390 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9391 //case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: reset must be processed immediately
9392 uata_ctl_queue:
9393 KdPrint2((PRINT_PREFIX "put to queue (UNIATA)\n"));
9394 PostReq = UniataNeedQueueing(deviceExtension, chan, TopLevel);
9395
9396 if(PostReq || TopLevel) {
9397 UniataQueueRequest(chan, Srb);
9398 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9399 AtaReq->ReqState = REQ_STATE_QUEUED;
9400 }
9401 if(PostReq) {
9402 KdPrint2((PRINT_PREFIX "Non-empty queue (UNIATA)\n"));
9403 status = SRB_STATUS_PENDING;
9404
9405 KdPrint2((PRINT_PREFIX "AtapiStartIo: Already have %d request(s)!\n", chan->queue_depth));
9406 goto complete_req;
9407 }
9408 } // end switch (AtaCtl->hdr.ControlCode)
9409
9410 /* process request */
9411 switch (AtaCtl->hdr.ControlCode) {
9412 case IOCTL_SCSI_MINIPORT_UNIATA_FIND_DEVICES:
9413
9414 KdPrint2((PRINT_PREFIX "AtapiStartIo: rescan bus\n"));
9415
9416 if(len < pos+sizeof(AtaCtl->FindDelDev)) {
9417 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9418 pos+sizeof(AtaCtl->FindDelDev) ));
9419 goto wrong_buffer_size;
9420 }
9421 if(AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE) {
9422 KdPrint2((PRINT_PREFIX "AtapiStartIo: unhide from further detection\n"));
9423 if(AtaCtl->addr.TargetId != 0xff) {
9424 LunExt->DeviceFlags &= ~DFLAGS_HIDDEN;
9425 } else {
9426 }
9427 }
9428
9429 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
9430 AtapiStallExecution(1000 * 1000);
9431 }
9432
9433 FindDevices(HwDeviceExtension,
9434 ((AtaCtl->addr.TargetId == 0xff) && (AtaCtl->FindDelDev.Flags & UNIATA_ADD_FLAGS_UNHIDE))
9435 ? UNIATA_FIND_DEV_UNHIDE : 0,
9436 AtaCtl->addr.PathId);
9437 status = SRB_STATUS_SUCCESS;
9438
9439 break;
9440
9441 case IOCTL_SCSI_MINIPORT_UNIATA_DELETE_DEVICE: {
9442
9443 KdPrint2((PRINT_PREFIX "AtapiStartIo: remove %#x:%#x\n", AtaCtl->addr.PathId, AtaCtl->addr.TargetId));
9444
9445 if(len < pos+sizeof(AtaCtl->FindDelDev)) {
9446 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9447 pos+sizeof(AtaCtl->FindDelDev) ));
9448 goto wrong_buffer_size;
9449 }
9450 LunExt->DeviceFlags = 0;
9451 if(AtaCtl->FindDelDev.Flags & UNIATA_REMOVE_FLAGS_HIDE) {
9452 KdPrint2((PRINT_PREFIX "AtapiStartIo: hide from further detection\n"));
9453 //LunExt->DeviceFlags |= DFLAGS_HIDDEN;
9454 UniataForgetDevice(LunExt);
9455 }
9456
9457 for(i=0; i<AtaCtl->FindDelDev.WaitForPhysicalLink && i<30; i++) {
9458 AtapiStallExecution(1000 * 1000);
9459 }
9460
9461 status = SRB_STATUS_SUCCESS;
9462 break;
9463 }
9464 case IOCTL_SCSI_MINIPORT_UNIATA_SET_MAX_MODE: {
9465
9466 KdPrint2((PRINT_PREFIX "AtapiStartIo: Set transfer mode\n"));
9467
9468 if(len < pos+sizeof(AtaCtl->SetMode)) {
9469 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9470 pos+sizeof(AtaCtl->SetMode) ));
9471 goto wrong_buffer_size;
9472 }
9473 if(AtaCtl->SetMode.OrigMode != IOMODE_NOT_SPECIFIED) {
9474 LunExt->OrigTransferMode = (UCHAR)(AtaCtl->SetMode.OrigMode);
9475 }
9476 if(AtaCtl->SetMode.MaxMode != IOMODE_NOT_SPECIFIED) {
9477 LunExt->LimitedTransferMode = (UCHAR)(AtaCtl->SetMode.MaxMode);
9478 if(LunExt->LimitedTransferMode >
9479 LunExt->OrigTransferMode) {
9480 // check for incorrect value
9481 LunExt->LimitedTransferMode =
9482 LunExt->OrigTransferMode;
9483 }
9484 }
9485 LunExt->TransferMode = min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode);
9486
9487 LunExt->DeviceFlags |= DFLAGS_REINIT_DMA; // force PIO/DMA reinit
9488 if(AtaCtl->SetMode.ApplyImmediately) {
9489 AtapiDmaInit__(deviceExtension, LunExt);
9490 }
9491 /* LunExt->TransferMode =
9492 LunExt->LimitedTransferMode = (UCHAR)(setTransferMode->Mode);*/
9493 status = SRB_STATUS_SUCCESS;
9494 break;
9495 }
9496 case IOCTL_SCSI_MINIPORT_UNIATA_GET_MODE: {
9497
9498 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get transfer mode\n"));
9499
9500 if(len < pos+sizeof(AtaCtl->GetMode)) {
9501 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9502 pos+sizeof(AtaCtl->GetMode) ));
9503 goto wrong_buffer_size;
9504 }
9505 AtaCtl->GetMode.OrigMode = LunExt->OrigTransferMode;
9506 AtaCtl->GetMode.MaxMode = LunExt->LimitedTransferMode;
9507 AtaCtl->GetMode.CurrentMode = LunExt->TransferMode;
9508 AtaCtl->GetMode.PhyMode = LunExt->PhyTransferMode;
9509
9510 status = SRB_STATUS_SUCCESS;
9511 break;
9512 }
9513 case IOCTL_SCSI_MINIPORT_UNIATA_GET_VERSION: {
9514
9515 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get version\n"));
9516
9517 if(len < pos+sizeof(AtaCtl->Version)) {
9518 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9519 pos+sizeof(AtaCtl->Version) ));
9520 goto wrong_buffer_size;
9521 }
9522 AtaCtl->Version.Length = sizeof(GETDRVVERSION);
9523 AtaCtl->Version.VersionMj = UNIATA_VER_MJ;
9524 AtaCtl->Version.VersionMn = UNIATA_VER_MN;
9525 AtaCtl->Version.SubVerMj = UNIATA_VER_SUB_MJ;
9526 AtaCtl->Version.SubVerMn = UNIATA_VER_SUB_MN;
9527
9528 status = SRB_STATUS_SUCCESS;
9529 break;
9530 }
9531 case IOCTL_SCSI_MINIPORT_UNIATA_ADAPTER_INFO: {
9532
9533 KdPrint2((PRINT_PREFIX "AtapiStartIo: Get adapter info\n"));
9534
9535 if(len < pos+sizeof(AtaCtl->AdapterInfo)) {
9536 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtaCtl Buffer too small: %#x < %#x\n", len,
9537 pos+sizeof(AtaCtl->AdapterInfo) ));
9538 goto wrong_buffer_size;
9539 }
9540 AtaCtl->AdapterInfo.HeaderLength = sizeof(ADAPTERINFO);
9541
9542 AtaCtl->AdapterInfo.DevID = deviceExtension->DevID;
9543 AtaCtl->AdapterInfo.RevID = deviceExtension->RevID;
9544 AtaCtl->AdapterInfo.slotNumber = deviceExtension->slotNumber;
9545 AtaCtl->AdapterInfo.SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
9546 AtaCtl->AdapterInfo.DevIndex = deviceExtension->DevIndex;
9547 AtaCtl->AdapterInfo.Channel = deviceExtension->Channel;
9548 AtaCtl->AdapterInfo.HbaCtrlFlags = deviceExtension->HbaCtrlFlags;
9549 AtaCtl->AdapterInfo.simplexOnly= deviceExtension->simplexOnly;
9550 AtaCtl->AdapterInfo.MemIo = FALSE;/*deviceExtension->MemIo;*/
9551 AtaCtl->AdapterInfo.UnknownDev = deviceExtension->UnknownDev;
9552 AtaCtl->AdapterInfo.MasterDev = deviceExtension->MasterDev;
9553 AtaCtl->AdapterInfo.MaxTransferMode = deviceExtension->MaxTransferMode;
9554 AtaCtl->AdapterInfo.HwFlags = deviceExtension->HwFlags;
9555 AtaCtl->AdapterInfo.OrigAdapterInterfaceType = deviceExtension->OrigAdapterInterfaceType;
9556 AtaCtl->AdapterInfo.BusInterruptLevel = deviceExtension->BusInterruptLevel;
9557 AtaCtl->AdapterInfo.InterruptMode = deviceExtension->InterruptMode;
9558 AtaCtl->AdapterInfo.BusInterruptVector = deviceExtension->BusInterruptVector;
9559 AtaCtl->AdapterInfo.NumberChannels = deviceExtension->NumberChannels;
9560 AtaCtl->AdapterInfo.NumberLuns = (UCHAR)deviceExtension->NumberLuns;
9561 AtaCtl->AdapterInfo.AdapterInterfaceType = deviceExtension->AdapterInterfaceType;
9562 if(deviceExtension->FullDevName) {
9563 strncpy(AtaCtl->AdapterInfo.DeviceName, deviceExtension->FullDevName, 64);
9564 }
9565 AtaCtl->AdapterInfo.ChanInfoValid = FALSE;
9566 AtaCtl->AdapterInfo.LunInfoValid = FALSE;
9567 AtaCtl->AdapterInfo.ChanHeaderLengthValid = TRUE;
9568
9569 pos += AtaCtl->AdapterInfo.HeaderLength;
9570
9571 // zero tail
9572 RtlZeroMemory(((PCHAR)AtaCtl)+pos,
9573 len-pos);
9574
9575 if(len >= pos+AtaCtl->AdapterInfo.NumberChannels*sizeof(CHANINFO)) {
9576 PCHANINFO ChanInfo = (PCHANINFO)( ((PCHAR)AtaCtl)+pos );
9577 PHW_CHANNEL cur_chan;
9578 KdPrint2((PRINT_PREFIX "AtapiStartIo: Fill channel info\n"));
9579 for(i=0;i<AtaCtl->AdapterInfo.NumberChannels;i++) {
9580 KdPrint2((PRINT_PREFIX "chan[%d] %x\n", i, cur_chan));
9581 cur_chan = &(deviceExtension->chan[i]);
9582 ChanInfo->MaxTransferMode = cur_chan->MaxTransferMode;
9583 ChanInfo->ChannelCtrlFlags = cur_chan->ChannelCtrlFlags;
9584 RtlCopyMemory(&(ChanInfo->QueueStat), &(cur_chan->QueueStat), sizeof(ChanInfo->QueueStat));
9585 ChanInfo->ReorderCount = cur_chan->ReorderCount;
9586 ChanInfo->IntersectCount = cur_chan->IntersectCount;
9587 ChanInfo->TryReorderCount = cur_chan->TryReorderCount;
9588 ChanInfo->TryReorderHeadCount = cur_chan->TryReorderHeadCount;
9589 ChanInfo->TryReorderTailCount = cur_chan->TryReorderTailCount;
9590 //ChanInfo->opt_MaxTransferMode = cur_chan->opt_MaxTransferMode;
9591 ChanInfo++;
9592 }
9593 AtaCtl->AdapterInfo.ChanInfoValid = TRUE;
9594 AtaCtl->AdapterInfo.ChanHeaderLength = sizeof(*ChanInfo);
9595 }
9596
9597 status = SRB_STATUS_SUCCESS;
9598 break;
9599 }
9600 case IOCTL_SCSI_MINIPORT_UNIATA_RESETBB: {
9601
9602 KdPrint2((PRINT_PREFIX "AtapiStartIo: Forget BB list\n"));
9603
9604 ForgetBadBlocks(LunExt);
9605
9606 status = SRB_STATUS_SUCCESS;
9607 break;
9608 }
9609 case IOCTL_SCSI_MINIPORT_UNIATA_RESET_DEVICE: {
9610
9611 KdPrint2((PRINT_PREFIX "AtapiStartIo: Reset device\n"));
9612
9613 if(bad_ldev) {
9614 goto do_bus_reset;
9615 } else {
9616 UniataUserDeviceReset(deviceExtension, LunExt, AtaCtl->addr.PathId);
9617 }
9618
9619 status = SRB_STATUS_SUCCESS;
9620 break;
9621 }
9622 default :
9623 KdPrint2((PRINT_PREFIX "AtapiStartIo: invalid IoControl %#x for -UNIATA- signature\n",
9624 AtaCtl->hdr.ControlCode ));
9625 status = SRB_STATUS_INVALID_REQUEST;
9626 break;
9627 }
9628
9629 } else {
9630 KdPrint2((PRINT_PREFIX "AtapiStartIo: IoControl signature incorrect. Send %s, expected %s or %s\n",
9631 ((PSRB_IO_CONTROL)(Srb->DataBuffer))->Signature,
9632 "SCSIDISK", "-UNIATA-"));
9633
9634 status = SRB_STATUS_INVALID_REQUEST;
9635 break;
9636 }
9637
9638 break;
9639 } // end SRB_FUNCTION_IO_CONTROL
9640 default:
9641
9642 KdPrint2((PRINT_PREFIX "AtapiStartIo: Unknown IOCTL\n"));
9643 // Indicate unsupported command.
9644 status = SRB_STATUS_INVALID_REQUEST;
9645
9646 // break;
9647
9648 } // end switch
9649
9650 complete_req:
9651
9652 PathId = Srb->PathId;
9653 TargetId = Srb->TargetId;
9654 Lun = Srb->Lun;
9655
9656 if (status != SRB_STATUS_PENDING) {
9657
9658 KdPrint2((PRINT_PREFIX
9659 "AtapiStartIo: Srb %#x complete with status %#x\n",
9660 Srb,
9661 status));
9662
9663 // Set status in SRB.
9664 Srb->SrbStatus = (UCHAR)status;
9665
9666 if(chan && Srb) {
9667 KdPrint2((PRINT_PREFIX "AtapiStartIo: AtapiDmaDBSync(%x, %x)\n", chan, Srb));
9668 AtapiDmaDBSync(chan, Srb);
9669 }
9670 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataRemoveRequest(%x, %x)\n", chan, Srb));
9671 UniataRemoveRequest(chan, Srb);
9672 // Indicate command complete.
9673 KdPrint2((PRINT_PREFIX "AtapiStartIo: ScsiPortNotification\n"));
9674 ScsiPortNotification(RequestComplete,
9675 deviceExtension,
9676 Srb);
9677
9678 KdPrint2((PRINT_PREFIX "AtapiStartIo: UniataGetCurRequest\n"));
9679 // Remove current Srb & get next one
9680 if((Srb = UniataGetCurRequest(chan))) {
9681 AtaReq = (PATA_REQ)(Srb->SrbExtension);
9682 if(AtaReq->ReqState > REQ_STATE_QUEUED) {
9683 // current request is under precessing, thus
9684 // we should do nothing here
9685 Srb = NULL;
9686 }
9687 }
9688 KdPrint2((PRINT_PREFIX "AtapiStartIo: chan %x, Src %x\n", chan, Srb));
9689 if(!chan) {
9690 //ASSERT(TopLevel);
9691 }
9692 }
9693 KdPrint2((PRINT_PREFIX "AtapiStartIo: next Srb %x\n", Srb));
9694
9695 } while (Srb && (status != SRB_STATUS_PENDING));
9696
9697 KdPrint2((PRINT_PREFIX "AtapiStartIo: query PORT for next request\n"));
9698 // Indicate ready for next request.
9699 ScsiPortNotification(NextRequest,
9700 deviceExtension,
9701 NULL);
9702
9703 ScsiPortNotification(NextLuRequest,
9704 deviceExtension,
9705 PathId,
9706 TargetId,
9707 Lun);
9708
9709 return TRUE;
9710
9711 } // end AtapiStartIo__()
9712
9713
9714 void
9715 NTAPI
9716 UniataInitAtaCommands()
9717 {
9718 int i;
9719 UCHAR command;
9720 UCHAR flags;
9721
9722 KdPrint2((PRINT_PREFIX "UniataInitAtaCommands:\n"));
9723
9724 for(i=0; i<256; i++) {
9725
9726 flags = 0;
9727 command = i;
9728
9729 //KdPrint2((PRINT_PREFIX "cmd %2.2x: ", command));
9730
9731 switch(command) {
9732 case IDE_COMMAND_READ_DMA48:
9733 case IDE_COMMAND_READ_DMA_Q48:
9734 case IDE_COMMAND_READ_STREAM_DMA48:
9735 case IDE_COMMAND_READ_STREAM48:
9736 case IDE_COMMAND_WRITE_DMA48:
9737 case IDE_COMMAND_WRITE_DMA_Q48:
9738 case IDE_COMMAND_READ_DMA_Q:
9739 case IDE_COMMAND_READ_DMA:
9740 case IDE_COMMAND_WRITE_DMA:
9741 case IDE_COMMAND_WRITE_DMA_Q:
9742 case IDE_COMMAND_WRITE_STREAM_DMA48:
9743 case IDE_COMMAND_WRITE_STREAM48:
9744 case IDE_COMMAND_WRITE_FUA_DMA48:
9745 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9746 case IDE_COMMAND_READ_LOG_DMA48:
9747 case IDE_COMMAND_WRITE_LOG_DMA48:
9748 case IDE_COMMAND_TRUSTED_RCV_DMA:
9749 case IDE_COMMAND_TRUSTED_SEND_DMA:
9750 case IDE_COMMAND_DATA_SET_MGMT:
9751 //KdPrint2((PRINT_PREFIX "DMA "));
9752 flags |= ATA_CMD_FLAG_DMA;
9753 }
9754
9755 switch(command) {
9756 case IDE_COMMAND_WRITE_FUA_DMA48:
9757 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9758 case IDE_COMMAND_WRITE_MUL_FUA48:
9759
9760 flags |= ATA_CMD_FLAG_FUA;
9761 /* FALL THROUGH */
9762
9763 case IDE_COMMAND_READ48:
9764 case IDE_COMMAND_READ_DMA48:
9765 case IDE_COMMAND_READ_DMA_Q48:
9766 case IDE_COMMAND_READ_MUL48:
9767 case IDE_COMMAND_READ_STREAM_DMA48:
9768 case IDE_COMMAND_READ_STREAM48:
9769 case IDE_COMMAND_WRITE48:
9770 case IDE_COMMAND_WRITE_DMA48:
9771 case IDE_COMMAND_WRITE_DMA_Q48:
9772 case IDE_COMMAND_WRITE_MUL48:
9773 case IDE_COMMAND_WRITE_STREAM_DMA48:
9774 case IDE_COMMAND_WRITE_STREAM48:
9775 case IDE_COMMAND_FLUSH_CACHE48:
9776 case IDE_COMMAND_VERIFY48:
9777
9778 //KdPrint2((PRINT_PREFIX "48 "));
9779 flags |= ATA_CMD_FLAG_48;
9780 /* FALL THROUGH */
9781
9782 case IDE_COMMAND_READ:
9783 case IDE_COMMAND_READ_MULTIPLE:
9784 case IDE_COMMAND_READ_DMA:
9785 case IDE_COMMAND_READ_DMA_Q:
9786 case IDE_COMMAND_WRITE:
9787 case IDE_COMMAND_WRITE_MULTIPLE:
9788 case IDE_COMMAND_WRITE_DMA:
9789 case IDE_COMMAND_WRITE_DMA_Q:
9790 case IDE_COMMAND_FLUSH_CACHE:
9791 case IDE_COMMAND_VERIFY:
9792
9793 //KdPrint2((PRINT_PREFIX "LBA "));
9794 flags |= ATA_CMD_FLAG_LBAIOsupp;
9795 }
9796
9797 switch(command) {
9798 case IDE_COMMAND_READ_NATIVE_SIZE48:
9799 case IDE_COMMAND_SET_NATIVE_SIZE48:
9800 // we cannot set LBA flag for these commands to avoid BadBlock handling
9801 //flags |= ATA_CMD_FLAG_LBAIOsupp;
9802 flags |= ATA_CMD_FLAG_48;
9803
9804 case IDE_COMMAND_READ_NATIVE_SIZE:
9805 case IDE_COMMAND_SET_NATIVE_SIZE:
9806
9807 flags |= ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_FUA;
9808 }
9809
9810 flags |= ATA_CMD_FLAG_48supp;
9811
9812 switch (command) {
9813 case IDE_COMMAND_READ:
9814 command = IDE_COMMAND_READ48; break;
9815 case IDE_COMMAND_READ_MULTIPLE:
9816 command = IDE_COMMAND_READ_MUL48; break;
9817 case IDE_COMMAND_READ_DMA:
9818 command = IDE_COMMAND_READ_DMA48; break;
9819 case IDE_COMMAND_READ_DMA_Q:
9820 command = IDE_COMMAND_READ_DMA_Q48; break;
9821 case IDE_COMMAND_WRITE:
9822 command = IDE_COMMAND_WRITE48; break;
9823 case IDE_COMMAND_WRITE_MULTIPLE:
9824 command = IDE_COMMAND_WRITE_MUL48; break;
9825 case IDE_COMMAND_WRITE_DMA:
9826 command = IDE_COMMAND_WRITE_DMA48; break;
9827 case IDE_COMMAND_WRITE_DMA_Q:
9828 command = IDE_COMMAND_WRITE_DMA_Q48; break;
9829 case IDE_COMMAND_FLUSH_CACHE:
9830 command = IDE_COMMAND_FLUSH_CACHE48; break;
9831 // case IDE_COMMAND_READ_NATIVE_SIZE:
9832 // command = IDE_COMMAND_READ_NATIVE_SIZE48; break;
9833 case IDE_COMMAND_SET_NATIVE_SIZE:
9834 command = IDE_COMMAND_SET_NATIVE_SIZE48; break;
9835 case IDE_COMMAND_VERIFY:
9836 command = IDE_COMMAND_VERIFY48; break;
9837 default:
9838 //KdPrint2((PRINT_PREFIX "!28->48 "));
9839 flags &= ~ATA_CMD_FLAG_48supp;
9840 }
9841
9842 switch (command) {
9843 case IDE_COMMAND_READ:
9844 case IDE_COMMAND_READ_MULTIPLE:
9845 case IDE_COMMAND_READ_DMA48:
9846 case IDE_COMMAND_READ_DMA_Q48:
9847 case IDE_COMMAND_READ_STREAM_DMA48:
9848 case IDE_COMMAND_READ_STREAM48:
9849 case IDE_COMMAND_READ_DMA_Q:
9850 case IDE_COMMAND_READ_DMA:
9851 case IDE_COMMAND_READ_LOG_DMA48:
9852 case IDE_COMMAND_TRUSTED_RCV_DMA:
9853 case IDE_COMMAND_IDENTIFY:
9854 case IDE_COMMAND_ATAPI_IDENTIFY:
9855 //KdPrint2((PRINT_PREFIX "RD "));
9856 flags |= ATA_CMD_FLAG_In;
9857 break;
9858 case IDE_COMMAND_WRITE:
9859 case IDE_COMMAND_WRITE_MULTIPLE:
9860 case IDE_COMMAND_WRITE_DMA48:
9861 case IDE_COMMAND_WRITE_DMA_Q48:
9862 case IDE_COMMAND_WRITE_DMA:
9863 case IDE_COMMAND_WRITE_DMA_Q:
9864 case IDE_COMMAND_WRITE_STREAM_DMA48:
9865 case IDE_COMMAND_WRITE_STREAM48:
9866 case IDE_COMMAND_WRITE_FUA_DMA48:
9867 case IDE_COMMAND_WRITE_FUA_DMA_Q48:
9868 //KdPrint2((PRINT_PREFIX "WR "));
9869 flags |= ATA_CMD_FLAG_Out;
9870 break;
9871 }
9872
9873 //KdPrint2((PRINT_PREFIX "\t -> %2.2x (%2.2x)\n", command, flags));
9874 AtaCommands48[i] = command;
9875 AtaCommandFlags[i] = flags;
9876 }
9877 } // end UniataInitAtaCommands()
9878
9879 /*++
9880
9881 Routine Description:
9882
9883 Installable driver initialization entry point for system.
9884
9885 Arguments:
9886
9887 Driver Object
9888
9889 Return Value:
9890
9891 Status from ScsiPortInitialize()
9892
9893 --*/
9894 extern "C"
9895 ULONG
9896 NTAPI
9897 DriverEntry(
9898 IN PVOID DriverObject,
9899 IN PVOID Argument2
9900 )
9901 {
9902 HW_INITIALIZATION_DATA_COMMON hwInitializationData;
9903 ULONG adapterCount;
9904 ULONG i, c, alt;
9905 ULONG statusToReturn, newStatus;
9906 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
9907 BOOLEAN ReEnter = FALSE;
9908 WCHAR a;
9909 #ifndef USE_REACTOS_DDK
9910 NTSTATUS status;
9911 #endif
9912
9913 PCONFIGURATION_INFORMATION GlobalConfig = IoGetConfigurationInformation();
9914 BOOLEAN PrimaryClaimed = FALSE;
9915 BOOLEAN SecondaryClaimed = FALSE;
9916
9917 LARGE_INTEGER t0, t1;
9918
9919 Connect_DbgPrint();
9920 KdPrint2((PRINT_PREFIX "%s", (PCCHAR)ver_string));
9921 a = (WCHAR)strlen(ver_string);
9922
9923 g_opt_Verbose = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PrintLogo", 0);
9924 if(g_opt_Verbose) {
9925 _PrintNtConsole("Universal ATA driver v 0." UNIATA_VER_STR "\n");
9926 }
9927
9928 if(!SavedDriverObject) {
9929 SavedDriverObject = (PDRIVER_OBJECT)DriverObject;
9930 #ifdef USE_REACTOS_DDK
9931 KdPrint(("UniATA Init: OS should be ReactOS\n"));
9932 MajorVersion=0x04;
9933 MinorVersion=0x01;
9934 BuildNumber=1;
9935 #else
9936 // we are here for the 1st time
9937 // init CrossNT and get OS version
9938 if(!NT_SUCCESS(status = CrNtInit(SavedDriverObject, RegistryPath))) {
9939 KdPrint(("UniATA Init: CrNtInit failed with status %#x\n", status));
9940 //HalDisplayString((PUCHAR)"DbgPrnHkInitialize: CrNtInit failed\n");
9941 return status;
9942 }
9943 #endif // USE_REACTOS_DDK
9944 KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, KeNumberProcessors));
9945
9946 KeQuerySystemTime(&t0);
9947 do {
9948 KeQuerySystemTime(&t1);
9949 } while(t0.QuadPart == t1.QuadPart);
9950 t0=t1;
9951 g_Perf=0;
9952 do {
9953 KeQuerySystemTime(&t1);
9954 g_Perf++;
9955 } while(t0.QuadPart == t1.QuadPart);
9956 g_PerfDt = (ULONG)((t1.QuadPart - t0.QuadPart)/10);
9957 KdPrint(("Performance calibration: dt=%d, counter=%I64d\n", g_PerfDt, g_Perf ));
9958 } else {
9959 KdPrint(("UniATA Init: ReEnter\n"));
9960 ReEnter = TRUE;
9961 }
9962
9963 // (re)read bad block list
9964 InitBadBlocks(NULL);
9965
9966 if(!ReEnter) {
9967 // init ATA command translation table
9968 UniataInitAtaCommands();
9969 // get registry path to settings
9970 RtlCopyMemory(&SavedRegPath, RegistryPath, sizeof(UNICODE_STRING));
9971 SavedRegPath.Buffer = (PWCHAR)&SavedRegPathBuffer;
9972 SavedRegPath.Length = min(RegistryPath->Length, 255*sizeof(WCHAR));
9973 SavedRegPath.MaximumLength = 255*sizeof(WCHAR);
9974 RtlCopyMemory(SavedRegPath.Buffer, RegistryPath->Buffer, SavedRegPath.Length);
9975 SavedRegPath.Buffer[SavedRegPath.Length/sizeof(WCHAR)] = 0;
9976 }
9977
9978 if(WinVer_Id() >= WinVer_2k) {
9979 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"1", 0)) {
9980 KdPrint(("UniATA: Behave as WDM, mlia (1)\n"));
9981 WinVer_WDM_Model = TRUE;
9982 }
9983 if(AtapiRegCheckParameterValue(NULL, L"Paramaters\\PnpInterface", L"5", 0)) {
9984 KdPrint(("UniATA: Behave as WDM, mlia (5)\n"));
9985 WinVer_WDM_Model = TRUE;
9986 }
9987 }
9988
9989 SkipRaids = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"SkipRaids", 1);
9990 ForceSimplex = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"ForceSimplex", 0);
9991 #ifdef _DEBUG
9992 g_LogToDisplay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"LogToDisplay", 0);
9993 #endif //_DEBUG
9994
9995 statusToReturn = 0xffffffff;
9996
9997 // Zero out structure.
9998 RtlZeroMemory(((PCHAR)&hwInitializationData), sizeof(hwInitializationData));
9999
10000 // Set size of hwInitializationData.
10001 hwInitializationData.comm.HwInitializationDataSize =
10002 sizeof(hwInitializationData.comm) +
10003 // sizeof(hwInitializationData.nt4) +
10004 ((WinVer_Id() <= WinVer_NT) ? 0 : sizeof(hwInitializationData.w2k));
10005 KdPrint(("HwInitializationDataSize = %x\n", hwInitializationData.comm.HwInitializationDataSize));
10006
10007 // Set entry points.
10008 hwInitializationData.comm.HwInitialize = (PHW_INITIALIZE)AtapiHwInitialize;
10009 hwInitializationData.comm.HwResetBus = (PHW_RESET_BUS)AtapiResetController;
10010 hwInitializationData.comm.HwStartIo = (PHW_STARTIO)AtapiStartIo;
10011 hwInitializationData.comm.HwInterrupt = (PHW_INTERRUPT)AtapiInterrupt;
10012
10013 // Specify size of extensions.
10014 hwInitializationData.comm.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
10015 hwInitializationData.comm.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
10016 hwInitializationData.comm.SrbExtensionSize = sizeof(ATA_REQ);
10017
10018 // Indicate PIO device.
10019 hwInitializationData.comm.MapBuffers = TRUE;
10020 // Set PnP-specific API
10021 if(WinVer_Id() > WinVer_NT) {
10022 KdPrint(("set NeedPhysicalAddresses = TRUE\n"));
10023 hwInitializationData.comm.NeedPhysicalAddresses = TRUE;
10024 KdPrint(("set AtapiAdapterControl() ptr\n"));
10025 hwInitializationData.w2k.HwAdapterControl = (PHW_ADAPTER_CONTROL)AtapiAdapterControl;
10026 }
10027
10028 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE enum supported BusMaster Devices\n"));
10029
10030 if(!ReEnter) {
10031
10032 g_opt_VirtualMachine = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualMachineType", g_opt_VirtualMachine);
10033 if(g_opt_VirtualMachine > VM_MAX_KNOWN) {
10034 g_opt_VirtualMachine = 0;
10035 }
10036 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"VirtualBox", (g_opt_VirtualMachine == VM_VBOX))) {
10037 g_opt_VirtualMachine = VM_VBOX;
10038 }
10039 // Pre-scan PCI bus, also check if we are under VM
10040 UniataEnumBusMasterController(DriverObject, Argument2);
10041
10042 switch(g_opt_VirtualMachine) {
10043 case VM_VBOX:
10044 KdPrint2((PRINT_PREFIX "adjust options for VirtualBox\n"));
10045 // adjust options for VirtualBox
10046 g_opt_WaitBusyCount = 20000;
10047 g_opt_WaitBusyDelay = 150;
10048 g_opt_WaitDrqDelay = 100;
10049 g_opt_WaitBusyLongCount = 20000;
10050 g_opt_MaxIsrWait = 200;
10051 g_opt_AtapiSendDisableIntr = 0;
10052 g_opt_AtapiDmaRawRead = FALSE;
10053 break;
10054 }
10055
10056 if(!hasPCI) {
10057 KdPrint2((PRINT_PREFIX "old slow machine, adjust timings\n"));
10058 // old slow machine, adjust timings
10059 g_opt_WaitBusyCount = 20000;
10060 g_opt_WaitBusyDelay = 150;
10061 g_opt_WaitDrqDelay = 100;
10062 g_opt_WaitBusyLongCount = 20000;
10063 g_opt_MaxIsrWait = 200;
10064 }
10065
10066 g_opt_WaitBusyCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyCount", g_opt_WaitBusyCount); // 200 vs 20000
10067 g_opt_WaitBusyDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyDelay", g_opt_WaitBusyDelay); // 10 vs 150
10068 g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100
10069 g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000
10070 g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250
10071 g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr); // 1 vs 0
10072 g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead); // 1 vs 0
10073 g_opt_MaxIsrWait = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait); // 40 vs xxx
10074 }
10075
10076 // Look for legacy ISA-bridged PCI IDE controller (onboard)
10077 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for legacy ISA-bridged PCI IDE controller (onboard)\n"));
10078 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: BMListLen %d\n", BMListLen));
10079 for (i=0; i <BMListLen; i++) {
10080
10081 if(!BMList[i].MasterDev) {
10082 KdPrint2((PRINT_PREFIX "!BMList[i].MasterDev\n"));
10083 break;
10084 }
10085 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
10086 break;
10087 }
10088 if(ReEnter) {
10089 KdPrint2((PRINT_PREFIX "ReEnter, skip it\n"));
10090 if(BMList[i].ChanInitOk & 0x03) {
10091 KdPrint2((PRINT_PREFIX "Already initialized, skip it\n"));
10092 statusToReturn =
10093 newStatus = STATUS_SUCCESS;
10094 }
10095 continue;
10096 }
10097 //BMList[i].AltInitMasterDev = (UCHAR)0xff;
10098
10099 if(GlobalConfig->AtDiskPrimaryAddressClaimed)
10100 PrimaryClaimed = TRUE;
10101 if(GlobalConfig->AtDiskSecondaryAddressClaimed)
10102 SecondaryClaimed = TRUE;
10103
10104 if(!WinVer_WDM_Model && !PrimaryClaimed && !SecondaryClaimed &&
10105 !(BMList[i].ChanInitOk & 0x80)) {
10106 newStatus = UniataClaimLegacyPCIIDE(i);
10107 if(newStatus != STATUS_SUCCESS) {
10108 KdPrint2((PRINT_PREFIX "Can't acquire PCI part of BusMaster, try as pure ISA later.\n"));
10109 break;
10110 }
10111 }
10112
10113 if(g_opt_Verbose) {
10114 _PrintNtConsole("Init standard Dual-channel PCI ATA controller:");
10115 }
10116
10117
10118 for(alt = 0; alt < (ULONG)(WinVer_WDM_Model ? 1 : 2) ; alt++) {
10119
10120 for(c=0; c<2; c++) {
10121
10122 if(AtapiRegCheckDevValue(NULL, c, DEVNUM_NOT_SPECIFIED, L"IgnoreIsaCompatiblePci", 0)) {
10123 break;
10124 }
10125 if(c==0) {
10126 if(PrimaryClaimed) {
10127 KdPrint2((PRINT_PREFIX "Primary already claimed\n"));
10128 continue;
10129 }
10130 } else
10131 if(c==1) {
10132 if(SecondaryClaimed) {
10133 KdPrint2((PRINT_PREFIX "Secondary already claimed\n"));
10134 continue;
10135 }
10136 }
10137
10138 if((WinVer_Id() < WinVer_2k)) {
10139 // do not even try if already claimed
10140 if(c==0) {
10141 GlobalConfig->AtDiskPrimaryAddressClaimed = FALSE;
10142 } else
10143 if(c==1) {
10144 GlobalConfig->AtDiskSecondaryAddressClaimed = FALSE;
10145 }
10146 }
10147 if(!WinVer_WDM_Model) {
10148 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
10149 } else {
10150 // in WDM model things are different....
10151 hwInitializationData.comm.HwFindAdapter = (c == 0) ?
10152 UniataFindCompatBusMasterController1 : UniataFindCompatBusMasterController2;
10153 }
10154 hwInitializationData.comm.NumberOfAccessRanges = 6;
10155 hwInitializationData.comm.AdapterInterfaceType = Isa;
10156
10157 if(!WinVer_WDM_Model) {
10158 BMList[i].channel = (UCHAR)c;
10159 }
10160
10161 KdPrint2((PRINT_PREFIX "Try init channel %d, method %d\n", c, alt));
10162 newStatus = ScsiPortInitialize(DriverObject,
10163 Argument2,
10164 &hwInitializationData.comm,
10165 (PVOID)(i | (alt ? 0x80000000 : 0)));
10166 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10167 if (newStatus < statusToReturn) {
10168 statusToReturn = newStatus;
10169 }
10170 if (newStatus == STATUS_SUCCESS) {
10171 if(WinVer_Id() < WinVer_2k) {
10172 // This should be done in HwInitialize under w2k+ to ensure that
10173 // channel is actually initialized
10174 BMList[i].ChanInitOk |= 0x01 << c;
10175 } else {
10176 if(BMList[i].ChanInitOk & (0x01 << c)) {
10177 KdPrint2((PRINT_PREFIX "HwInit passed\n"));
10178 }
10179 }
10180 /*
10181 if(BMList[i].MasterDev && (WinVer_Id() > WinVer_NT)) {
10182 c = 1; // this will break our for()
10183 BMList[i].ChanInitOk |= 0x01 << c;
10184 }
10185 */
10186 }
10187 }
10188 /* if(WinVer_Id() >= WinVer_2k) {
10189 // the following didn't work under higher OSes,
10190 // until we move setting of FLAGS to HwInit
10191 KdPrint2((PRINT_PREFIX "make still one attempt\n"));
10192 continue;
10193 }*/
10194 if(BMList[i].ChanInitOk & 0x03) {
10195 // Under NT we receive status immediately, so
10196 // we can omit alternative init method if STATUS_SUCCESS returned.
10197 // Under w2k+ we relay on flags, set in HwInitialize.
10198 KdPrint2((PRINT_PREFIX "Ok, no more retries required\n"));
10199 break;
10200 } else
10201 if(WinVer_Id() >= WinVer_2k) {
10202 // try AltInit if HwInit was not called immediately under w2k+
10203 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
10204 } else {
10205 // if (WinVer_Id() == WinVer_NT) and some error occured
10206 // try alternative init method
10207 KdPrint2((PRINT_PREFIX "make still one attempt w2k+\n"));
10208 }
10209 } // for(alt...)
10210 if(g_opt_Verbose) {
10211 if(BMList[i].ChanInitOk & 0x03) {
10212 _PrintNtConsole(" OK\n");
10213 } else {
10214 _PrintNtConsole(" failed\n");
10215 }
10216 }
10217
10218 }
10219
10220 /* KeBugCheckEx(0xc000000e,
10221 (i << 16) | BMList[0].ChanInitOk,
10222 c,
10223 newStatus, statusToReturn);*/
10224
10225 // Look for PCI IDE controller
10226 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for PCI IDE controller\n"));
10227 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: i %d, BMListLen %d\n", i, BMListLen));
10228 for (; i <BMListLen; i++) {
10229
10230 if(AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreNativePci", 0)) {
10231 break;
10232 }
10233 /* if(BMList[i].MasterDev)
10234 continue;*/
10235 if(g_opt_Verbose) {
10236 _PrintNtConsole("Init PCI ATA controller Vendor/Dev %4.4s//%4.4s at PCI Address %d:%d:%d",
10237 BMList[i].VendorId, BMList[i].DeviceId,
10238 BMList[i].busNumber,
10239 BMList[i].slotNumber % PCI_MAX_FUNCTION,
10240 (BMList[i].slotNumber / PCI_MAX_FUNCTION) % PCI_MAX_DEVICES);
10241 }
10242
10243 hwInitializationData.comm.HwFindAdapter = UniataFindBusMasterController;
10244 hwInitializationData.comm.NumberOfAccessRanges = 6;
10245 hwInitializationData.comm.AdapterInterfaceType = PCIBus;
10246
10247 hwInitializationData.comm.VendorId = (PVOID)BMList[i].VendorId;
10248 hwInitializationData.comm.VendorIdLength = (USHORT) BMList[i].VendorIdLength;
10249 hwInitializationData.comm.DeviceId = (PVOID)BMList[i].DeviceId;
10250 hwInitializationData.comm.DeviceIdLength = (USHORT) BMList[i].DeviceIdLength;
10251
10252 BMList[i].channel = 0/*(UCHAR)c*/;
10253
10254 KdPrint2((PRINT_PREFIX "Try init %4.4s %4.4s \n",
10255 hwInitializationData.comm.VendorId,
10256 hwInitializationData.comm.DeviceId));
10257 newStatus = ScsiPortInitialize(DriverObject,
10258 Argument2,
10259 &hwInitializationData.comm,
10260 (PVOID)i);
10261 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10262 if(newStatus == (ULONG)STATUS_DEVICE_DOES_NOT_EXIST && BMList[i].NeedAltInit) {
10263 // Note: this is actually a BUG in scsiport.sys
10264 // It stops scanning PCI bus when reaches empty PCI Function inside Slot
10265 // However, this PCI Slot may have higher non-empty Functions
10266 // UniATA will perform all staff instead of ScsiPort under NT,
10267 // but for ReactOS it is better to patch ScsiPort.
10268 KdPrint2((PRINT_PREFIX "STATUS_DEVICE_DOES_NOT_EXIST, try workaround\n"));
10269 hwInitializationData.comm.AdapterInterfaceType = Isa;
10270 newStatus = ScsiPortInitialize(DriverObject,
10271 Argument2,
10272 &hwInitializationData.comm,
10273 (PVOID)(i | 0x80000000));
10274 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x (2)\n", newStatus));
10275 }
10276 if (newStatus < statusToReturn)
10277 statusToReturn = newStatus;
10278
10279 if(g_opt_Verbose) {
10280 if(newStatus == STATUS_SUCCESS) {
10281 _PrintNtConsole(" OK\n");
10282 } else {
10283 _PrintNtConsole(" failed\n");
10284 }
10285 }
10286
10287 }
10288
10289 /* KeBugCheckEx(0xc000000e,
10290 i,
10291 c,
10292 newStatus, statusToReturn);*/
10293
10294 // --------------
10295
10296 hwInitializationData.comm.VendorId = 0;
10297 hwInitializationData.comm.VendorIdLength = 0;
10298 hwInitializationData.comm.DeviceId = 0;
10299 hwInitializationData.comm.DeviceIdLength = 0;
10300
10301 if(!BMListLen) {
10302 hwInitializationData.comm.SrbExtensionSize = //FIELD_OFFSET(ATA_REQ, ata);
10303 sizeof(ATA_REQ);
10304 KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", hwInitializationData.comm.SrbExtensionSize));
10305 }
10306
10307 // The adapter count is used by the find adapter routine to track how
10308 // which adapter addresses have been tested.
10309
10310 // Indicate 2 access ranges and reset FindAdapter.
10311 hwInitializationData.comm.NumberOfAccessRanges = 2;
10312 hwInitializationData.comm.HwFindAdapter = AtapiFindController;
10313
10314 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreIsa", 0)) {
10315 // Indicate ISA bustype.
10316 hwInitializationData.comm.AdapterInterfaceType = Isa;
10317 adapterCount = 0;
10318
10319 // Call initialization for ISA bustype.
10320 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for ISA Controllers\n"));
10321 newStatus = ScsiPortInitialize(DriverObject,
10322 Argument2,
10323 &hwInitializationData.comm,
10324 &adapterCount);
10325 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10326 if (newStatus < statusToReturn)
10327 statusToReturn = newStatus;
10328 }
10329 if(!AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreMca", 0)) {
10330 // Set up for MCA
10331 KdPrint2((PRINT_PREFIX "\n\nATAPI IDE: Look for MCA Controllers\n"));
10332 hwInitializationData.comm.AdapterInterfaceType = MicroChannel;
10333 adapterCount = 0;
10334
10335 newStatus = ScsiPortInitialize(DriverObject,
10336 Argument2,
10337 &hwInitializationData.comm,
10338 &adapterCount);
10339 KdPrint2((PRINT_PREFIX "ScsiPortInitialize Status %#x\n", newStatus));
10340 if (newStatus < statusToReturn)
10341 statusToReturn = newStatus;
10342 }
10343 InDriverEntry = FALSE;
10344
10345 KdPrint2((PRINT_PREFIX "\n\nLeave UNIATA MiniPort DriverEntry with status %#x\n", statusToReturn));
10346
10347 return statusToReturn;
10348
10349 } // end DriverEntry()
10350
10351
10352 PSCSI_REQUEST_BLOCK
10353 NTAPI
10354 BuildMechanismStatusSrb(
10355 IN PVOID HwDeviceExtension,
10356 IN PSCSI_REQUEST_BLOCK Srb
10357 )
10358 {
10359 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10360 PSCSI_REQUEST_BLOCK srb;
10361 PCDB cdb;
10362 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
10363
10364 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
10365
10366 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
10367
10368 srb->PathId = (UCHAR)(Srb->PathId);
10369 srb->TargetId = (UCHAR)(Srb->TargetId);
10370 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
10371 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
10372
10373 // Set flags to disable synchronous negociation.
10374 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
10375
10376 // Set timeout to 4 seconds.
10377 srb->TimeOutValue = 4;
10378
10379 srb->CdbLength = 6;
10380 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusData);
10381 srb->DataTransferLength = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
10382 srb->SrbExtension = AtaReq;
10383
10384 // Set CDB operation code.
10385 cdb = (PCDB)srb->Cdb;
10386 cdb->MECH_STATUS.OperationCode = SCSIOP_MECHANISM_STATUS;
10387 cdb->MECH_STATUS.AllocationLength[1] = sizeof(MECHANICAL_STATUS_INFORMATION_HEADER);
10388
10389 KdPrint2((PRINT_PREFIX " MechanismStatusSrb %#x\n", srb));
10390
10391 return srb;
10392 } // end BuildMechanismStatusSrb()
10393
10394 #endif //UNIATA_CORE
10395
10396 PSCSI_REQUEST_BLOCK
10397 NTAPI
10398 BuildRequestSenseSrb (
10399 IN PVOID HwDeviceExtension,
10400 IN PSCSI_REQUEST_BLOCK Srb
10401 )
10402 {
10403 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10404 PSCSI_REQUEST_BLOCK srb;
10405 PCDB cdb;
10406 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
10407
10408 srb = &(deviceExtension->chan[GET_CHANNEL(Srb)].InternalSrb);
10409
10410 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK));
10411
10412 srb->PathId = (UCHAR)(Srb->PathId);
10413 srb->TargetId = (UCHAR)(Srb->TargetId);
10414 srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
10415 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
10416
10417 // Set flags to disable synchronous negociation.
10418 srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
10419
10420 // Set timeout to 2 seconds.
10421 srb->TimeOutValue = 4;
10422
10423 srb->CdbLength = 6;
10424 srb->DataBuffer = &(deviceExtension->chan[GET_CHANNEL(Srb)].MechStatusSense);
10425 srb->DataTransferLength = sizeof(SENSE_DATA);
10426 srb->SrbExtension = AtaReq;
10427
10428 // Set CDB operation code.
10429 cdb = (PCDB)srb->Cdb;
10430 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
10431 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
10432
10433 KdPrint2((PRINT_PREFIX " RequestSenseSrb %#x\n", srb));
10434
10435 return srb;
10436 } // end BuildRequestSenseSrb()
10437
10438 #ifndef UNIATA_CORE
10439
10440 ULONG
10441 NTAPI
10442 AtapiRegCheckDevLunValue(
10443 IN PVOID HwDeviceExtension,
10444 IN PCWCH NamePrefix,
10445 IN ULONG chan,
10446 IN ULONG dev,
10447 IN PCWSTR Name,
10448 IN ULONG Default
10449 )
10450 {
10451 WCHAR namex[160];
10452 ULONG val = Default;
10453
10454 val = AtapiRegCheckParameterValue(
10455 HwDeviceExtension, NamePrefix, Name, val);
10456
10457 if(chan != CHAN_NOT_SPECIFIED) {
10458 swprintf(namex, L"%s\\Chan_%1.1d", NamePrefix, chan);
10459 val = AtapiRegCheckParameterValue(
10460 HwDeviceExtension, namex, Name, val);
10461 if(dev != DEVNUM_NOT_SPECIFIED) {
10462 swprintf(namex, L"%s\\Chan_%1.1d\\%s", NamePrefix, chan, (dev & 0x01) ? L"Lun_1" : L"Lun_0");
10463 val = AtapiRegCheckParameterValue(
10464 HwDeviceExtension, namex, Name, val);
10465 }
10466 }
10467 return val;
10468 } // end AtapiRegCheckDevLunValue()
10469
10470 ULONG
10471 NTAPI
10472 EncodeVendorStr(
10473 OUT PWCHAR Buffer,
10474 IN PUCHAR Str,
10475 IN ULONG Length
10476 )
10477 {
10478 ULONG i,j;
10479 WCHAR a;
10480
10481 for(i=0, j=0; i<Length; i++, j++) {
10482 // fix byte-order
10483 a = Str[i ^ 0x01];
10484 if(!a) {
10485 Buffer[j] = 0;
10486 return j;
10487 } else
10488 if(a == ' ') {
10489 Buffer[j] = '_';
10490 } else
10491 if((a == '_') ||
10492 (a == '#') ||
10493 (a == '\\') ||
10494 (a == '\"') ||
10495 (a == '\'') ||
10496 (a < ' ') ||
10497 (a >= 127)) {
10498 Buffer[j] = '#';
10499 j++;
10500 swprintf(Buffer+j, L"%2.2x", a);
10501 j++;
10502 } else {
10503 Buffer[j] = a;
10504 }
10505 }
10506 Buffer[j] = 0;
10507 return j;
10508 } // end EncodeVendorStr()
10509
10510 ULONG
10511 NTAPI
10512 AtapiRegCheckDevValue(
10513 IN PVOID HwDeviceExtension,
10514 IN ULONG chan,
10515 IN ULONG dev,
10516 IN PCWSTR Name,
10517 IN ULONG Default
10518 )
10519 {
10520 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10521 // WCHAR name0[11];
10522 // WCHAR name1[11+4+5];
10523 // WCHAR name2[11+4+4+10];
10524 // WCHAR name3[11+4+4+5+20];
10525 // WCHAR name3[11+4+4+5+20+1];
10526 WCHAR namex[160];
10527
10528 WCHAR namev[16];
10529 WCHAR named[16];
10530 WCHAR names[20];
10531
10532 IN ULONG VendorID;
10533 IN ULONG DeviceID;
10534 IN ULONG SlotNumber;
10535
10536 ULONG val = Default;
10537
10538 KdPrint(( " Parameter %ws\n", Name));
10539
10540 if(deviceExtension) {
10541 VendorID = deviceExtension->DevID & 0xffff;
10542 DeviceID = (deviceExtension->DevID >> 16) & 0xffff;
10543 SlotNumber = deviceExtension->slotNumber;
10544 } else {
10545 VendorID = 0xffff;
10546 DeviceID = 0xffff;
10547 SlotNumber = 0xffffffff;
10548 }
10549
10550 val = AtapiRegCheckDevLunValue(
10551 HwDeviceExtension, L"Parameters", chan, dev, Name, val);
10552
10553 if(deviceExtension) {
10554 if(deviceExtension->AdapterInterfaceType == PCIBus) {
10555 // PCI
10556 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex);
10557 swprintf(namex, L"Parameters%s", namev);
10558 val = AtapiRegCheckDevLunValue(
10559 HwDeviceExtension, namex, chan, dev, Name, val);
10560
10561
10562 swprintf(namev, L"\\Ven_%4.4x", VendorID);
10563 swprintf(named, L"\\Dev_%4.4x", DeviceID);
10564 swprintf(names, L"\\Slot_%8.8x", SlotNumber);
10565
10566 swprintf(namex, L"Parameters%s", namev);
10567 val = AtapiRegCheckDevLunValue(
10568 HwDeviceExtension, namex, chan, dev, Name, val);
10569
10570 swprintf(namex, L"Parameters%s%s", namev, named);
10571 val = AtapiRegCheckDevLunValue(
10572 HwDeviceExtension, namex, chan, dev, Name, val);
10573
10574 swprintf(namex, L"Parameters%s%s%s", namev, named, names);
10575 val = AtapiRegCheckDevLunValue(
10576 HwDeviceExtension, namex, chan, dev, Name, val);
10577 } else
10578 if(deviceExtension->AdapterInterfaceType == Isa) {
10579 // Isa
10580 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen);
10581 swprintf(namex, L"Parameters%s", namev);
10582 val = AtapiRegCheckDevLunValue(
10583 HwDeviceExtension, namex, chan, dev, Name, val);
10584
10585 swprintf(namev, L"\\ISA_%d", deviceExtension->DevIndex);
10586 swprintf(namex, L"Parameters%s", namev);
10587 val = AtapiRegCheckDevLunValue(
10588 HwDeviceExtension, namex, chan, dev, Name, val);
10589
10590 } else
10591 if(deviceExtension->AdapterInterfaceType == MicroChannel) {
10592 // MicroChannel
10593 swprintf(namev, L"\\IDE_%d", deviceExtension->DevIndex+BMListLen+IsaCount);
10594 swprintf(namex, L"Parameters%s", namev);
10595 val = AtapiRegCheckDevLunValue(
10596 HwDeviceExtension, namex, chan, dev, Name, val);
10597
10598 swprintf(namev, L"\\MCA_%d", deviceExtension->DevIndex);
10599 swprintf(namex, L"Parameters%s", namev);
10600 val = AtapiRegCheckDevLunValue(
10601 HwDeviceExtension, namex, chan, dev, Name, val);
10602
10603 }
10604 }
10605
10606 KdPrint(( " Parameter %ws = %#x\n", Name, val));
10607 return val;
10608
10609 } // end AtapiRegCheckDevValue()
10610
10611 /*
10612 The user must specify that Xxx is to run on the platform
10613 by setting the registry value HKEY_LOCAL_MACHINE\System\CurrentControlSet\
10614 Services\UniATA\Xxx:REG_DWORD:Zzz.
10615
10616 The user can override the global setting to enable or disable Xxx on a
10617 specific cdrom device by setting the key HKEY_LOCAL_MACHINE\System\
10618 CurrentControlSet\Services\UniATA\Parameters\Device<N>\Xxx:REG_DWORD to one or zero.
10619
10620 If this registry value does not exist or contains the value zero then
10621 the timer to check for media change does not run.
10622
10623 Arguments:
10624
10625 RegistryPath - pointer to the unicode string inside
10626 ...\CurrentControlSet\Services\UniATA
10627 DeviceNumber - The number of the HBA device object
10628
10629 Returns: Registry Key value
10630 */
10631 ULONG
10632 NTAPI
10633 AtapiRegCheckParameterValue(
10634 IN PVOID HwDeviceExtension,
10635 IN PCWSTR PathSuffix,
10636 IN PCWSTR Name,
10637 IN ULONG Default
10638 )
10639 {
10640 #define ITEMS_TO_QUERY 2 // always 1 greater than what is searched
10641
10642 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10643 NTSTATUS status;
10644 LONG zero = Default;
10645
10646 RTL_QUERY_REGISTRY_TABLE parameters[ITEMS_TO_QUERY];
10647
10648 // LONG tmp = 0;
10649 LONG doRun = Default;
10650
10651 PUNICODE_STRING RegistryPath = &SavedRegPath;
10652
10653 UNICODE_STRING paramPath;
10654
10655 // <SavedRegPath>\<PathSuffix> -> <Name>
10656 // KdPrint(( "AtapiCheckRegValue: %ws -> %ws\n", PathSuffix, Name));
10657 // KdPrint(( "AtapiCheckRegValue: RegistryPath %ws\n", RegistryPath->Buffer));
10658
10659 paramPath.Length = 0;
10660 paramPath.MaximumLength = RegistryPath->Length +
10661 (wcslen(PathSuffix)+2)*sizeof(WCHAR);
10662 paramPath.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, paramPath.MaximumLength);
10663 if(!paramPath.Buffer) {
10664 KdPrint(("AtapiCheckRegValue: couldn't allocate paramPath\n"));
10665 return Default;
10666 }
10667
10668 RtlZeroMemory(paramPath.Buffer, paramPath.MaximumLength);
10669 RtlAppendUnicodeToString(&paramPath, RegistryPath->Buffer);
10670 RtlAppendUnicodeToString(&paramPath, L"\\");
10671 RtlAppendUnicodeToString(&paramPath, REGRTL_STR_PTYPE PathSuffix);
10672
10673 // Check for the Xxx value.
10674 RtlZeroMemory(parameters, (sizeof(RTL_QUERY_REGISTRY_TABLE)*ITEMS_TO_QUERY));
10675
10676 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
10677 parameters[0].Name = REGRTL_STR_PTYPE Name;
10678 parameters[0].EntryContext = &doRun;
10679 parameters[0].DefaultType = REG_DWORD;
10680 parameters[0].DefaultData = &zero;
10681 parameters[0].DefaultLength = sizeof(ULONG);
10682
10683 status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE /*| RTL_REGISTRY_OPTIONAL*/,
10684 paramPath.Buffer, parameters, NULL, NULL);
10685 if(NT_SUCCESS(status)) {
10686 KdPrint(( "AtapiCheckRegValue: %ws -> %ws is %#x\n", PathSuffix, Name, doRun));
10687 }
10688
10689 ExFreePool(paramPath.Buffer);
10690
10691 if(!NT_SUCCESS(status)) {
10692 doRun = Default;
10693 }
10694
10695 return doRun;
10696
10697 #undef ITEMS_TO_QUERY
10698
10699 } // end AtapiRegCheckParameterValue()
10700
10701
10702 SCSI_ADAPTER_CONTROL_STATUS
10703 NTAPI
10704 AtapiAdapterControl(
10705 IN PVOID HwDeviceExtension,
10706 IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
10707 IN PVOID Parameters
10708 )
10709 {
10710 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
10711 PSCSI_SUPPORTED_CONTROL_TYPE_LIST pControlTypeList;
10712 ULONG numberChannels = deviceExtension->NumberChannels;
10713 ULONG c;
10714 NTSTATUS status;
10715
10716 KdPrint(( "AtapiAdapterControl: %#x\n", ControlType));
10717
10718 switch(ControlType) {
10719 case ScsiQuerySupportedControlTypes: {
10720 BOOLEAN supportedTypes[ScsiAdapterControlMax] = {
10721 TRUE, // ScsiQuerySupportedControlTypes
10722 TRUE, // ScsiStopAdapter
10723 TRUE, // ScsiRestartAdapter
10724 FALSE, // ScsiSetBootConfig
10725 FALSE // ScsiSetRunningConfig
10726 };
10727
10728 ULONG lim = ScsiAdapterControlMax;
10729 ULONG i;
10730
10731 pControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST) Parameters;
10732
10733 if(pControlTypeList->MaxControlType < lim) {
10734 lim = pControlTypeList->MaxControlType;
10735 }
10736
10737 for(i = 0; i < lim; i++) {
10738 pControlTypeList->SupportedTypeList[i] = supportedTypes[i];
10739 }
10740
10741 break;
10742
10743 }
10744 case ScsiStopAdapter: {
10745
10746 KdPrint(( "AtapiAdapterControl: ScsiStopAdapter\n"));
10747 // Shut down all interrupts on the adapter. They'll get re-enabled
10748 // by the initialization routines.
10749 for (c = 0; c < numberChannels; c++) {
10750 AtapiResetController(deviceExtension, c);
10751 AtapiDisableInterrupts(deviceExtension, c);
10752 }
10753 if(deviceExtension->AdapterInterfaceType == PCIBus) {
10754 // we must never get here for non-PCI
10755 status = UniataDisconnectIntr2(HwDeviceExtension);
10756 BMList[deviceExtension->DevIndex].Isr2Enable = FALSE;
10757 }
10758 break;
10759 }
10760 case ScsiRestartAdapter: {
10761
10762 KdPrint(( "AtapiAdapterControl: ScsiRestartAdapter\n"));
10763 // Enable all the interrupts on the adapter while port driver call
10764 // for power up an HBA that was shut down for power management
10765
10766 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
10767 status = UniataConnectIntr2(HwDeviceExtension);
10768 for (c = 0; c < numberChannels; c++) {
10769 AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, c);
10770 FindDevices(HwDeviceExtension, 0, c);
10771 AtapiEnableInterrupts(deviceExtension, c);
10772 AtapiHwInitialize__(deviceExtension, c);
10773 }
10774 if(deviceExtension->Isr2DevObj) {
10775 // we must never get here for non-PCI
10776 BMList[deviceExtension->DevIndex].Isr2Enable = TRUE;
10777 }
10778
10779 break;
10780 }
10781
10782 default: {
10783 KdPrint(( "AtapiAdapterControl: default => return ScsiAdapterControlUnsuccessful\n"));
10784 return ScsiAdapterControlUnsuccessful;
10785 }
10786 }
10787
10788 return ScsiAdapterControlSuccess;
10789 } // end AtapiAdapterControl()
10790
10791 #endif //UNIATA_CORE
10792
10793 extern "C"
10794 NTHALAPI
10795 VOID
10796 NTAPI
10797 HalDisplayString (
10798 PUCHAR String
10799 );
10800
10801 #define DEBUG_MSG_BUFFER_SIZE 512
10802
10803 extern "C"
10804 VOID
10805 _cdecl
10806 _PrintNtConsole(
10807 PCCH DebugMessage,
10808 ...
10809 )
10810 {
10811 int len;
10812 UCHAR dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE];
10813 // UNICODE_STRING msgBuff;
10814 va_list ap;
10815 va_start(ap, DebugMessage);
10816
10817 len = _vsnprintf((PCHAR)&dbg_print_tmp_buff[0], DEBUG_MSG_BUFFER_SIZE-1, DebugMessage, ap);
10818
10819 dbg_print_tmp_buff[DEBUG_MSG_BUFFER_SIZE-1] = 0;
10820
10821 //DbgPrint(((PCHAR)&(dbg_print_tmp_buff[0]))); // already done in KdPrint macro
10822 HalDisplayString(dbg_print_tmp_buff);
10823
10824 #ifdef _DEBUG
10825 if(g_LogToDisplay > 1) {
10826 AtapiStallExecution(g_LogToDisplay*1000);
10827 }
10828 #endif // _DEBUG
10829
10830 va_end(ap);
10831
10832 } // end PrintNtConsole()
10833