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