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