|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1991 Microsoft Corporation
4:
5: Module Name:
6:
7: aha174x.c
8:
9: Abstract:
10:
11: This is the port driver for the AHA174X SCSI adapter.
12:
13: Authors:
14:
15: Mike Glass
16:
17: Environment:
18:
19: kernel mode only
20:
21: Notes:
22:
23: Revision History:
24:
25: --*/
26:
27: #include "miniport.h"
28: #include "aha174x.h" // includes scsi.h
29:
30: //
31: // Device extension
32: //
33:
34: typedef struct _HW_DEVICE_EXTENSION {
35:
36: PEISA_CONTROLLER EisaController;
37:
38: UCHAR HostTargetId;
39:
40: PSCSI_REQUEST_BLOCK PendingSrb;
41:
42: UCHAR RequestCount[8][8];
43:
44: } HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
45:
46: //
47: // Define the maximum number of outstanding I/O requests per logical unit.
48: //
49:
50: #define MAX_QUEUE_DEPTH 2
51:
52:
53: //
54: // Function declarations
55: //
56: // Functions that start with 'Aha174x' are entry points
57: // for the OS port driver.
58: //
59:
60: ULONG
61: DriverEntry(
62: IN PVOID DriverObject,
63: IN PVOID Argument2
64: );
65:
66: ULONG
67: Aha174xEntry(
68: IN PVOID DriverObject,
69: IN PVOID Argument2
70: );
71:
72: ULONG
73: Aha174xConfiguration(
74: IN PVOID DeviceExtension,
75: IN PVOID Context,
76: IN PVOID BusInformation,
77: IN PCHAR ArgumentString,
78: IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
79: OUT PBOOLEAN Again
80: );
81:
82: BOOLEAN
83: Aha174xInitialize(
84: IN PVOID DeviceExtension
85: );
86:
87: BOOLEAN
88: Aha174xStartIo(
89: IN PVOID DeviceExtension,
90: IN PSCSI_REQUEST_BLOCK Srb
91: );
92:
93: BOOLEAN
94: Aha174xInterrupt(
95: IN PVOID DeviceExtension
96: );
97:
98: BOOLEAN
99: Aha174xResetBus(
100: IN PVOID HwDeviceExtension,
101: IN ULONG PathId
102: );
103:
104: //
105: // This function is called from Aha174xStartIo.
106: //
107:
108: VOID
109: A174xBuildEcb(
110: IN PHW_DEVICE_EXTENSION DeviceExtension,
111: IN PSCSI_REQUEST_BLOCK Srb
112: );
113:
114: //
115: // This function is called from A174xBuildEcb.
116: //
117:
118: VOID
119: A174xBuildSgl(
120: IN PHW_DEVICE_EXTENSION DeviceExtension,
121: IN PSCSI_REQUEST_BLOCK Srb
122: );
123:
124: VOID
125: A174xBuildRequestSense(
126: IN PVOID HwDeviceExtension,
127: IN PSCSI_REQUEST_BLOCK Srb
128: );
129:
130: BOOLEAN
131: A174xSendCommand(
132: IN PHW_DEVICE_EXTENSION DeviceExtension,
133: IN UCHAR OperationCode,
134: IN ULONG Address
135: );
136:
137: //
138: // This function is called from Aha174xInterrupt.
139: //
140:
141: VOID
142: A174xMapStatus(
143: IN PHW_DEVICE_EXTENSION DeviceExtension,
144: IN PSCSI_REQUEST_BLOCK Srb,
145: IN PSTATUS_BLOCK StatusBlock
146: );
147:
148:
149: ULONG
150: DriverEntry (
151: IN PVOID DriverObject,
152: IN PVOID Argument2
153: )
154:
155: /*++
156:
157: Routine Description:
158:
159: Installable driver initialization entry point for system.
160:
161: Arguments:
162:
163: Driver Object
164:
165: Return Value:
166:
167: Status from ScsiPortInitialize()
168:
169: --*/
170:
171: {
172: return Aha174xEntry(DriverObject, Argument2);
173:
174: } // end DriverEntry()
175:
176:
177: ULONG
178: Aha174xEntry(
179: IN PVOID DriverObject,
180: IN PVOID Argument2
181: )
182:
183: /*++
184:
185: Routine Description:
186:
187: This routine is called from DriverEntry if this driver is installable
188: or directly from the system if the driver is built into the kernel.
189: It scans the EISA slots looking for an AHA174X that is configured
190: to the ENHANCED mode.
191:
192: Arguments:
193:
194: Driver Object
195:
196: Return Value:
197:
198: Status from ScsiPortInitialize()
199:
200: --*/
201:
202: {
203: HW_INITIALIZATION_DATA hwInitializationData;
204: ULONG i;
205: ULONG AdapterCount = 0;
206:
207: DebugPrint((1,"\n\nSCSI Aha174x MiniPort Driver\n"));
208:
209: //
210: // Zero out structure.
211: //
212:
213: for (i=0; i<sizeof(HW_INITIALIZATION_DATA); i++) {
214: ((PUCHAR)&hwInitializationData)[i] = 0;
215: }
216:
217: //
218: // Set size of hwInitializationData.
219: //
220:
221: hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
222:
223: //
224: // Set entry points.
225: //
226:
227: hwInitializationData.HwInitialize = Aha174xInitialize;
228: hwInitializationData.HwFindAdapter = Aha174xConfiguration;
229: hwInitializationData.HwStartIo = Aha174xStartIo;
230: hwInitializationData.HwInterrupt = Aha174xInterrupt;
231: hwInitializationData.HwResetBus = Aha174xResetBus;
232:
233: //
234: // Set number of access ranges and bus type.
235: //
236:
237: hwInitializationData.NumberOfAccessRanges = 2;
238: hwInitializationData.AdapterInterfaceType = Eisa;
239:
240: //
241: // Indicate no buffer mapping but will need physical addresses.
242: //
243:
244: hwInitializationData.NeedPhysicalAddresses = TRUE;
245:
246: //
247: // Indicate auto request sense is supported.
248: //
249:
250: hwInitializationData.MultipleRequestPerLu = TRUE;
251: hwInitializationData.AutoRequestSense = TRUE;
252:
253: //
254: // Specify size of extensions.
255: //
256:
257: hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
258:
259: //
260: // Ask for SRB extensions for ECBs.
261: //
262:
263: hwInitializationData.SrbExtensionSize = sizeof(ECB);
264:
265: return ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &AdapterCount);
266:
267: } // end Aha174xEntry()
268:
269:
270: ULONG
271: Aha174xConfiguration(
272: IN PVOID HwDeviceExtension,
273: IN PVOID Context,
274: IN PVOID BusInformation,
275: IN PCHAR ArgumentString,
276: IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
277: OUT PBOOLEAN Again
278: )
279:
280: /*++
281:
282: Routine Description:
283:
284: This function is called by the OS-specific port driver after
285: the necessary storage has been allocated, to gather information
286: about the adapter's configuration.
287:
288: Arguments:
289:
290: HwDeviceExtension - HBA miniport driver's adapter data storage
291: ConfigInfo - Configuration information structure describing HBA
292:
293: Return Value:
294:
295: TRUE if adapter present in system
296:
297: --*/
298:
299: {
300: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
301: PEISA_CONTROLLER eisaController;
302: ULONG eisaSlotNumber;
303: PVOID eisaAddress;
304: UCHAR dataByte;
305: PULONG adapterCount = Context;
306:
307: //
308: // Check to see if adapter present in system.
309: //
310:
311: for (eisaSlotNumber=*adapterCount + 1; eisaSlotNumber<MAXIMUM_EISA_SLOTS; eisaSlotNumber++) {
312:
313: //
314: // Update the adapter count to indicate this slot has been checked.
315: //
316:
317: (*adapterCount)++;
318:
319: //
320: // Get the system address for this card.
321: // The card uses I/O space.
322: //
323:
324: eisaAddress = ScsiPortGetDeviceBase(deviceExtension,
325: ConfigInfo->AdapterInterfaceType,
326: ConfigInfo->SystemIoBusNumber,
327: ScsiPortConvertUlongToPhysicalAddress(0x1000 * eisaSlotNumber),
328: 0x1000,
329: TRUE);
330:
331: eisaController =
332: (PEISA_CONTROLLER)((PUCHAR)eisaAddress + EISA_ADDRESS_BASE);
333:
334: if ((ScsiPortReadPortUchar(&eisaController->BoardId[0]) == 0x04) &&
335: (ScsiPortReadPortUchar(&eisaController->BoardId[1]) == 0x90) &&
336: (ScsiPortReadPortUchar(&eisaController->BoardId[2]) == 0x00)) {
337:
338: DebugPrint((1,"AHA174X: Adapter found at EISA slot %d\n",
339: eisaSlotNumber));
340: #ifdef MIPS
341: //
342: // Add code to configure the device if necessary. This is only
343: // needed until we get an EISA configuration program.
344: //
345:
346: if (!(ScsiPortReadPortUchar(&eisaController->EBControl) & 0x1)) {
347:
348: //
349: // The card as not been configured. Jam in a default one.
350: // Enable the card, enable enhanced mode operation, set the
351: // irql to 14, set the target id to 7 and enable the DMA.
352: //
353:
354: ScsiPortWritePortUchar(&eisaController->EBControl, 1);
355: ScsiPortWritePortUchar(&eisaController->PortAddress, 0x80);
356: ScsiPortWritePortUchar(&eisaController->BiosAddress, 0x00);
357: ScsiPortWritePortUchar(&eisaController->Interrupt, 0x1d);
358: ScsiPortWritePortUchar(&eisaController->ScsiId, 0x7);
359: ScsiPortWritePortUchar(&eisaController->DmaChannel, 0x2);
360: ScsiPortStallExecution(1000);
361:
362: }
363: #endif
364: if (ScsiPortReadPortUchar(&eisaController->PortAddress) &
365: ENHANCED_INTERFACE_ENABLED) {
366:
367: //
368: // An adapter with the enhanced interface enabled was found.
369: //
370:
371: break;
372:
373: } else {
374:
375: DebugPrint((1,"AHA174X: Adapter is in STANDARD mode\n"));
376: }
377: }
378:
379: //
380: // If an adapter was not found unmap it.
381: //
382:
383: ScsiPortFreeDeviceBase(deviceExtension,
384: eisaAddress);
385:
386: } // end for (eisaSlotNumber ...
387:
388: if (!(eisaSlotNumber < MAXIMUM_EISA_SLOTS)) {
389:
390: //
391: // No adapter was found. Indicate that we are done and there are no
392: // more adapters here. Clear the adapter count for the next bus.
393: //
394:
395: *Again = FALSE;
396: *adapterCount = 0;
397: return SP_RETURN_NOT_FOUND;
398: }
399:
400: //
401: // There is still more to look at.
402: //
403:
404: *Again = TRUE;
405:
406: //
407: // Store base address of EISA registers in device extension.
408: //
409:
410: deviceExtension->EisaController = eisaController;
411:
412: ConfigInfo->InitiatorBusId[0] =
413: ScsiPortReadPortUchar(&eisaController->ScsiId) & 0x0F;
414:
415: deviceExtension->HostTargetId = ConfigInfo->InitiatorBusId[0];
416:
417: //
418: // Indicate maximum transfer length in bytes.
419: //
420:
421: ConfigInfo->MaximumTransferLength = MAXIMUM_TRANSFER_SIZE;
422:
423: //
424: // Maximum number of physical segments is 32.
425: //
426:
427: ConfigInfo->NumberOfPhysicalBreaks = MAXIMUM_SGL_DESCRIPTORS;
428:
429: ConfigInfo->ScatterGather = TRUE;
430: ConfigInfo->Master = TRUE;
431: ConfigInfo->NumberOfBuses = 1;
432:
433: //
434: // Get the system interrupt vector and IRQL.
435: //
436:
437: dataByte = ScsiPortReadPortUchar(&eisaController->Interrupt);
438: ConfigInfo->BusInterruptLevel = (dataByte & 7) + 9;
439:
440: //
441: // Determine level or edge interrupt.
442: //
443:
444: ConfigInfo->InterruptMode = dataByte & 0x08 ? Latched : LevelSensitive;
445:
446: //
447: // Fill in the access array information.
448: //
449:
450: (*ConfigInfo->AccessRanges)[0].RangeStart =
451: ScsiPortConvertUlongToPhysicalAddress(0x1000 * eisaSlotNumber + EISA_ADDRESS_BASE);
452: (*ConfigInfo->AccessRanges)[0].RangeLength = sizeof(EISA_CONTROLLER);
453: (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
454:
455:
456: //
457: // Determine the BIOS address.
458: //
459:
460: dataByte = ScsiPortReadPortUchar(&eisaController->BiosAddress);
461:
462: if (dataByte & BIOS_ENABLED) {
463:
464: dataByte &= BIOS_ADDRESS;
465:
466: //
467: // Calculate the bios base address.
468: //
469:
470: eisaSlotNumber = 0xC0000 + (dataByte * 0x4000);
471:
472: if (eisaSlotNumber < 0xF0000) {
473:
474: DebugPrint((1, "Aha174xConfiguration: Bios address at: %lx.\n", eisaSlotNumber));
475: (*ConfigInfo->AccessRanges)[1].RangeStart =
476: ScsiPortConvertUlongToPhysicalAddress(eisaSlotNumber);
477: (*ConfigInfo->AccessRanges)[1].RangeLength = BIOS_LENGTH;
478: (*ConfigInfo->AccessRanges)[1].RangeInMemory = TRUE;
479:
480: }
481: }
482:
483: return SP_RETURN_FOUND;
484:
485: } // end Aha174xConfiguration()
486:
487:
488: BOOLEAN
489: Aha174xInitialize(
490: IN PVOID HwDeviceExtension
491: )
492:
493: /*++
494:
495: Routine Description:
496:
497: Inititialize adapter and mailbox.
498:
499: Arguments:
500:
501: HwDeviceExtension - HBA miniport driver's adapter data storage
502:
503: Return Value:
504:
505: TRUE - if initialization successful.
506: FALSE - if initialization unsuccessful.
507:
508: --*/
509:
510: {
511: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
512:
513: //
514: // Reset Aha174x and SCSI bus.
515: //
516:
517: if (!Aha174xResetBus(deviceExtension, 0)) {
518:
519: DebugPrint((1, "Aha174xInitialize: Reset bus failed\n"));
520: return FALSE;
521:
522: } else {
523:
524: ScsiPortNotification(ResetDetected, deviceExtension, 0);
525:
526: return TRUE;
527: }
528:
529: } // end Aha174xInitialize()
530:
531:
532: BOOLEAN
533: Aha174xStartIo(
534: IN PVOID HwDeviceExtension,
535: IN PSCSI_REQUEST_BLOCK Srb
536: )
537:
538: /*++
539:
540: Routine Description:
541:
542: This routine is called from the SCSI port driver synchronized
543: with the kernel to send an ECB or issue an immediate command.
544:
545: Arguments:
546:
547: HwDeviceExtension - HBA miniport driver's adapter data storage
548: Srb - IO request packet
549:
550: Return Value:
551:
552: TRUE
553:
554: --*/
555:
556: {
557: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
558: PEISA_CONTROLLER eisaController = deviceExtension->EisaController;
559: PECB ecb;
560: PSCSI_REQUEST_BLOCK abortedSrb;
561: UCHAR opCode;
562: ULONG physicalEcb;
563: ULONG length;
564: ULONG i = 0;
565: UCHAR count = MAX_QUEUE_DEPTH;
566:
567: ASSERT(Srb->SrbStatus == SRB_STATUS_PENDING);
568:
569: //
570: // Get ECB from SRB.
571: //
572:
573: if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
574:
575: //
576: // Verify that SRB to abort is still outstanding.
577: //
578:
579: abortedSrb = ScsiPortGetSrb(deviceExtension,
580: Srb->PathId,
581: Srb->TargetId,
582: Srb->Lun,
583: Srb->QueueTag);
584:
585: if (abortedSrb != Srb->NextSrb ||
586: abortedSrb->SrbStatus != SRB_STATUS_PENDING) {
587:
588: DebugPrint((1, "A174xStartIo: SRB to abort already completed\n"));
589:
590: //
591: // Complete abort SRB.
592: //
593:
594: Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
595:
596: ScsiPortNotification(RequestComplete,
597: deviceExtension,
598: Srb);
599: //
600: // Adapter ready for next request.
601: //
602:
603: ScsiPortNotification(NextRequest,
604: deviceExtension,
605: NULL);
606:
607: return TRUE;
608: }
609:
610: //
611: // Get ECB to abort.
612: //
613:
614: ecb = Srb->NextSrb->SrbExtension;
615:
616: //
617: // Set abort SRB for completion.
618: //
619:
620: ecb->AbortSrb = Srb;
621:
622: } else {
623:
624: ecb = Srb->SrbExtension;
625:
626: //
627: // Save SRB back pointer in ECB.
628: //
629:
630: ecb->SrbAddress = Srb;
631: ecb->AbortSrb = NULL;
632:
633: }
634:
635: //
636: // Get ECB physical address.
637: //
638:
639: physicalEcb =
640: ScsiPortConvertPhysicalAddressToUlong(
641: ScsiPortGetPhysicalAddress(deviceExtension, NULL, ecb, &length));
642:
643: //
644: // Assume physical address is contiguous for size of ECB.
645: //
646:
647: ASSERT(length >= sizeof(ECB));
648:
649: switch (Srb->Function) {
650:
651: case SRB_FUNCTION_EXECUTE_SCSI:
652:
653: //
654: // Build ECB for regular request or request sense.
655: //
656:
657: if (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) {
658: A174xBuildRequestSense(deviceExtension, Srb);
659: } else {
660: A174xBuildEcb(deviceExtension, Srb);
661: }
662:
663: //
664: // Increment the request count.
665: //
666:
667: count = ++deviceExtension->RequestCount[Srb->TargetId][Srb->Lun];
668:
669: opCode = START_ECB;
670:
671: break;
672:
673: case SRB_FUNCTION_ABORT_COMMAND:
674:
675: DebugPrint((1, "Aha174xStartIo: Abort request received\n"));
676:
677: opCode = ABORT_ECB;
678:
679: break;
680:
681: default:
682:
683: //
684: // Set error, complete request
685: // and signal ready for next request.
686: //
687:
688: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
689:
690: ScsiPortNotification(RequestComplete,
691: deviceExtension,
692: Srb);
693:
694: ScsiPortNotification(NextRequest,
695: deviceExtension,
696: NULL);
697:
698: return TRUE;
699:
700: } // end switch
701:
702: if (!A174xSendCommand(deviceExtension,
703: (UCHAR)(opCode | Srb->TargetId),
704: physicalEcb)) {
705:
706: DebugPrint((1,"Aha174xStartIo: Send command timed out\n"));
707:
708: //
709: // Save the request utill a pending one completes.
710: //
711:
712: deviceExtension->PendingSrb = Srb;
713:
714: return(TRUE);
715:
716: }
717:
718: //
719: // Adapter ready for next request.
720: //
721:
722: if (count < MAX_QUEUE_DEPTH) {
723:
724: //
725: // Request another request for this logical unit.
726: //
727:
728: ScsiPortNotification(NextLuRequest,
729: deviceExtension,
730: Srb->PathId,
731: Srb->TargetId,
732: Srb->Lun);
733:
734: } else {
735:
736: //
737: // Request another request for this adapter.
738: //
739:
740: ScsiPortNotification(NextRequest,
741: deviceExtension,
742: Srb->PathId,
743: Srb->TargetId,
744: Srb->Lun);
745:
746: }
747:
748: return TRUE;
749:
750: } // end Aha174xStartIo()
751:
752:
753: BOOLEAN
754: Aha174xInterrupt(
755: IN PVOID HwDeviceExtension
756: )
757:
758: /*++
759:
760: Routine Description:
761:
762: This is the interrupt service routine for the Aha174x SCSI adapter.
763: It reads the interrupt register to determine if the adapter is indeed
764: the source of the interrupt and clears the interrupt at the device.
765: If the adapter is interrupting because a mailbox is full, the ECB is
766: retrieved to complete the request.
767:
768: Arguments:
769:
770: HwDeviceExtension - HBA miniport driver's adapter data storage
771:
772: Return Value:
773:
774: TRUE if MailboxIn full
775:
776: --*/
777:
778: {
779: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
780: PECB ecb;
781: PSCSI_REQUEST_BLOCK srb;
782: PEISA_CONTROLLER eisaController = deviceExtension->EisaController;
783: PSTATUS_BLOCK statusBlock;
784: UCHAR targetId;
785: UCHAR lun;
786: ULONG physicalEcb;
787: UCHAR interruptStatus;
788:
789: //
790: // Check interrupt pending.
791: //
792:
793: if (!(ScsiPortReadPortUchar(&eisaController->Status) &
794: INTERRUPT_PENDING)) {
795:
796: DebugPrint((4, "Aha174xInterrupt: Spurious interrupt\n"));
797: return FALSE;
798: }
799:
800: //
801: // Read interrupt status.
802: //
803:
804: interruptStatus = ScsiPortReadPortUchar(
805: &eisaController->InterruptStatus);
806:
807: //
808: // Get targetId
809: //
810:
811: targetId = interruptStatus & 0x0F;
812:
813: //
814: // Get physical address of ECB.
815: //
816:
817: physicalEcb = ScsiPortReadPortUlong(&eisaController->MailBoxIn);
818:
819: //
820: // Acknowledge interrupt.
821: //
822:
823: ScsiPortWritePortUchar(&eisaController->Control, CLEAR_INTERRUPT);
824:
825: //
826: // Check for pending requests. If there is one then start it.
827: //
828:
829: if (deviceExtension->PendingSrb != NULL) {
830:
831: srb = deviceExtension->PendingSrb;
832: deviceExtension->PendingSrb = NULL;
833:
834: Aha174xStartIo(deviceExtension, srb);
835:
836: }
837:
838: switch (interruptStatus>>4) {
839:
840: case ECB_COMPLETE_SUCCESS:
841: case ECB_COMPLETE_SUCCESS_RETRY:
842:
843: //
844: // Get virtual ECB address.
845: //
846:
847: ecb = ScsiPortGetVirtualAddress(deviceExtension, ScsiPortConvertUlongToPhysicalAddress(physicalEcb));
848:
849: //
850: // Make sure this was a valid physical address.
851: //
852:
853: if (ecb == NULL || ecb->SrbAddress == NULL) {
854: break;
855: }
856:
857: //
858: // Get SRB from ECB.
859: //
860:
861: srb = ecb->SrbAddress;
862:
863: //
864: // Clear SRB from ECB.
865: //
866:
867: ecb->SrbAddress = NULL;
868:
869: //
870: // Update SRB statuses.
871: //
872:
873: srb->SrbStatus = SRB_STATUS_SUCCESS;
874: srb->ScsiStatus = SCSISTAT_GOOD;
875:
876: //
877: // If there is a peneding abort request, then complete it.
878: // This adapter does not interrupt when an abort completes.
879: // So one of three cases will occur:
880: // The abort succeeds and the command is termainated.
881: // The abort is too late and command termainates.
882: // The abort fails but the command does not terminate.
883: // The first two cases are handled by completing the abort when the
884: // command completes. The last case is handled by the abort timing
885: // out.
886: //
887:
888: if (ecb->AbortSrb != NULL) {
889:
890: ecb->AbortSrb->SrbStatus = SRB_STATUS_SUCCESS;
891:
892: //
893: // Complete the abort request.
894: //
895:
896: ScsiPortNotification(
897: RequestComplete,
898: deviceExtension,
899: ecb->AbortSrb
900: );
901:
902: ecb->AbortSrb = NULL;
903: }
904:
905: if (deviceExtension->RequestCount[srb->TargetId][srb->Lun]--
906: == MAX_QUEUE_DEPTH) {
907:
908: //
909: // The adapter can now take another request for this device.
910: //
911:
912: ScsiPortNotification(NextLuRequest,
913: deviceExtension,
914: srb->PathId,
915: srb->TargetId,
916: srb->Lun);
917:
918: }
919:
920: //
921: // Call notification routine for the SRB.
922: //
923:
924: ScsiPortNotification(RequestComplete,
925: (PVOID)deviceExtension,
926: srb);
927:
928: return TRUE;
929:
930: case ECB_COMPLETE_ERROR:
931:
932: //
933: // Get virtual ECB address.
934: //
935:
936: ecb = ScsiPortGetVirtualAddress(deviceExtension, ScsiPortConvertUlongToPhysicalAddress(physicalEcb));
937:
938: //
939: // Make sure this was a valid physical address.
940: //
941:
942: if (ecb == NULL || ecb->SrbAddress == NULL) {
943: break;
944: }
945:
946: //
947: // Get SRB from ECB.
948: //
949:
950: srb = ecb->SrbAddress;
951:
952: //
953: // Clear SRB from ECB.
954: //
955:
956: ecb->SrbAddress = NULL;
957:
958: //
959: // Get Status Block virtual address.
960: //
961:
962: statusBlock = ScsiPortGetVirtualAddress(deviceExtension,
963: ScsiPortConvertUlongToPhysicalAddress(ecb->StatusBlockAddress));
964:
965: //
966: // If there is a peneding abort request, then complete it.
967: // This adapter does not interrupt when an abort completes.
968: // So one of three cases will occur:
969: // The abort succeeds and the command is termainated.
970: // The abort is too late and command termainates.
971: // The abort fails but the command does not terminate.
972: // The first two cases are handled by completing the abort when the
973: // command completes. The last case is handled by the abort timing
974: // out.
975: //
976:
977: if (ecb->AbortSrb != NULL) {
978:
979: ecb->AbortSrb->SrbStatus = SRB_STATUS_SUCCESS;
980:
981: //
982: // Complete the abort request.
983: //
984:
985: ScsiPortNotification(
986: RequestComplete,
987: deviceExtension,
988: ecb->AbortSrb
989: );
990:
991: ecb->AbortSrb = NULL;
992: }
993:
994: //
995: // Update SRB status.
996: //
997:
998: A174xMapStatus(deviceExtension, srb, statusBlock);
999:
1000: if (deviceExtension->RequestCount[srb->TargetId][srb->Lun]--
1001: == MAX_QUEUE_DEPTH) {
1002:
1003: //
1004: // The adapter can now take another request for this device.
1005: //
1006:
1007: ScsiPortNotification(NextLuRequest,
1008: deviceExtension,
1009: srb->PathId,
1010: srb->TargetId,
1011: srb->Lun);
1012:
1013: }
1014:
1015: //
1016: // Call notification routine for the SRB.
1017: //
1018:
1019: ScsiPortNotification(RequestComplete,
1020: (PVOID)deviceExtension,
1021: srb);
1022:
1023: return TRUE;
1024:
1025: case IMMEDIATE_COMMAND_SUCCESS:
1026:
1027: DebugPrint((2,"Aha174xInterrupt: Immediate command completed\n"));
1028: return TRUE;
1029:
1030: case ASYNCHRONOUS_EVENT_NOTIFICATION:
1031:
1032: //
1033: // Check if bus was reset.
1034: //
1035:
1036: if ((physicalEcb >> 24) == 0x23) {
1037:
1038: //
1039: // Clear the reqeust counts.
1040: //
1041:
1042: for (targetId = 0; targetId < 8; targetId++) {
1043: for (lun = 0; lun < 8; lun++) {
1044:
1045: deviceExtension->RequestCount[targetId][lun] = 0;
1046: }
1047: }
1048:
1049: //
1050: // Complete all outstanding requests.
1051: //
1052:
1053: ScsiPortCompleteRequest(deviceExtension,
1054: 0,
1055: SP_UNTAGGED,
1056: 0,
1057: SRB_STATUS_BUS_RESET);
1058:
1059:
1060: //
1061: // Notify operating system of SCSI bus reset.
1062: //
1063:
1064: ScsiPortNotification(ResetDetected,
1065: deviceExtension,
1066: NULL);
1067: }
1068:
1069: return TRUE;
1070:
1071: case IMMEDIATE_COMMAND_ERROR:
1072: default:
1073:
1074: DebugPrint((1, "A174xInterrupt: Unrecognized interrupt status %x\n",
1075: interruptStatus));
1076:
1077: //
1078: // Log the error.
1079: //
1080:
1081: ScsiPortLogError(
1082: HwDeviceExtension,
1083: NULL,
1084: 0,
1085: deviceExtension->HostTargetId,
1086: 0,
1087: SP_INTERNAL_ADAPTER_ERROR,
1088: 1 << 16 | interruptStatus
1089: );
1090:
1091: return TRUE;
1092:
1093: } // end switch
1094:
1095: //
1096: // A bad physcial address was return by the adapter.
1097: // Log it as an error.
1098: //
1099:
1100: ScsiPortLogError(
1101: HwDeviceExtension,
1102: NULL,
1103: 0,
1104: deviceExtension->HostTargetId,
1105: 0,
1106: SP_INTERNAL_ADAPTER_ERROR,
1107: 5 << 16 | interruptStatus
1108: );
1109:
1110: return TRUE;
1111:
1112: } // end Aha174xInterrupt()
1113:
1114:
1115: VOID
1116: A174xBuildEcb(
1117: IN PHW_DEVICE_EXTENSION DeviceExtension,
1118: IN PSCSI_REQUEST_BLOCK Srb
1119: )
1120:
1121: /*++
1122:
1123: Routine Description:
1124:
1125: Build ECB for Aha174x.
1126:
1127: Arguments:
1128:
1129: DeviceExtenson
1130: SRB
1131:
1132: Return Value:
1133:
1134: Nothing.
1135:
1136: --*/
1137:
1138: {
1139: PECB ecb = Srb->SrbExtension;
1140: PSTATUS_BLOCK statusBlock = &ecb->StatusBlock;
1141: ULONG length;
1142:
1143: //
1144: // Set ECB command.
1145: //
1146:
1147: ecb->Command = ECB_COMMAND_INITIATOR_COMMAND;
1148:
1149: //
1150: // Disable updating status block on success;
1151: //
1152:
1153: ecb->Flags[0] = ECB_FLAGS_DISABLE_STATUS_BLOCK;
1154:
1155: //
1156: // initialize ECB flags
1157: //
1158:
1159: ecb->Flags[1] = 0;
1160:
1161: //
1162: // Set transfer direction bit.
1163: //
1164:
1165: if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
1166:
1167: //
1168: // Write command.
1169: //
1170:
1171: ecb->Flags[1] |= ECB_FLAGS_WRITE;
1172:
1173: } else if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) {
1174:
1175: //
1176: // Read command.
1177: //
1178:
1179: ecb->Flags[1] |= ECB_FLAGS_READ;
1180: }
1181:
1182: //
1183: // Check if disconnect explicity forbidden.
1184: //
1185:
1186: if (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) {
1187:
1188: ecb->Flags[1] |= ECB_FLAGS_NO_DISCONNECT;
1189: }
1190:
1191: //
1192: // Set LUN (bits 16, 17 and 18).
1193: //
1194:
1195: ecb->Flags[1] |= Srb->Lun;
1196:
1197: //
1198: // Set CDB length and copy to ECB.
1199: //
1200:
1201: ecb->CdbLength = Srb->CdbLength;
1202: ScsiPortMoveMemory(ecb->Cdb, Srb->Cdb, Srb->CdbLength);
1203:
1204: //
1205: // Build SGL in ECB if data transfer.
1206: //
1207:
1208: if (Srb->DataTransferLength > 0) {
1209: ecb->Flags[0] |= ECB_FLAGS_SCATTER_GATHER;
1210: A174xBuildSgl(DeviceExtension, Srb);
1211: } else {
1212: ecb->SglLength = 0;
1213: }
1214:
1215: //
1216: // Set status block pointer.
1217: //
1218:
1219: ecb->StatusBlockAddress =
1220: ScsiPortConvertPhysicalAddressToUlong(
1221: ScsiPortGetPhysicalAddress(DeviceExtension,
1222: NULL,
1223: statusBlock,
1224: &length));
1225:
1226: ASSERT(length >= sizeof(STATUS_BLOCK));
1227:
1228: //
1229: // Setup auto sense if necessary.
1230: //
1231:
1232: if (Srb->SenseInfoBufferLength != 0 &&
1233: !(Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)) {
1234:
1235: //
1236: // Set the flag to enable auto sense and fill in the address and length
1237: // of the sense buffer.
1238: //
1239:
1240: ecb->Flags[0] |= ECB_FLAGS_AUTO_REQUEST_SENSE;
1241: ecb->SenseInfoLength = Srb->SenseInfoBufferLength;
1242: ecb->SenseInfoAddress = ScsiPortConvertPhysicalAddressToUlong(
1243: ScsiPortGetPhysicalAddress(DeviceExtension,
1244: Srb,
1245: Srb->SenseInfoBuffer,
1246: &length));
1247:
1248: ASSERT(length >= Srb->SenseInfoBufferLength);
1249:
1250: } else {
1251:
1252: ecb->SenseInfoLength = 0;
1253: }
1254:
1255: //
1256: // Zero out next ECB, request sense info fields
1257: // and statuses in status block.
1258: //
1259:
1260: ecb->NextEcb = 0;
1261: statusBlock->HaStatus = 0;
1262: statusBlock->TargetStatus = 0;
1263:
1264: return;
1265:
1266: } // end A174xBuildEcb()
1267:
1268:
1269: VOID
1270: A174xBuildSgl(
1271: IN PHW_DEVICE_EXTENSION DeviceExtension,
1272: IN PSCSI_REQUEST_BLOCK Srb
1273: )
1274:
1275: /*++
1276:
1277: Routine Description:
1278:
1279: This routine builds a scatter/gather descriptor list for the ECB.
1280:
1281: Arguments:
1282:
1283: DeviceExtension
1284: Srb
1285:
1286: Return Value:
1287:
1288: None
1289:
1290: --*/
1291:
1292: {
1293: PVOID dataPointer = Srb->DataBuffer;
1294: ULONG bytesLeft = Srb->DataTransferLength;
1295: PECB ecb = Srb->SrbExtension;
1296: PSGL sgl = &ecb->Sgl;
1297: ULONG physicalSgl;
1298: ULONG physicalAddress;
1299: ULONG length;
1300: ULONG descriptorCount = 0;
1301:
1302: //
1303: // Get physical SGL address.
1304: //
1305:
1306: physicalSgl = ScsiPortConvertPhysicalAddressToUlong(
1307: ScsiPortGetPhysicalAddress(DeviceExtension, NULL,
1308: sgl, &length));
1309:
1310: //
1311: // Assume physical memory contiguous for sizeof(SGL) bytes.
1312: //
1313:
1314: ASSERT(length >= sizeof(SGL));
1315:
1316: //
1317: // Create SGL segment descriptors.
1318: //
1319:
1320: do {
1321:
1322: //
1323: // Get physical address and length of contiguous
1324: // physical buffer.
1325: //
1326:
1327: physicalAddress =
1328: ScsiPortConvertPhysicalAddressToUlong(
1329: ScsiPortGetPhysicalAddress(DeviceExtension,
1330: Srb,
1331: dataPointer,
1332: &length));
1333:
1334: //
1335: // If length of physical memory is more
1336: // than bytes left in transfer, use bytes
1337: // left as final length.
1338: //
1339:
1340: if (length > bytesLeft) {
1341: length = bytesLeft;
1342: }
1343:
1344: sgl->Descriptor[descriptorCount].Address = physicalAddress;
1345: sgl->Descriptor[descriptorCount].Length = length;
1346:
1347: //
1348: // Adjust counts.
1349: //
1350:
1351: dataPointer = (PUCHAR)dataPointer + length;
1352: bytesLeft -= length;
1353: descriptorCount++;
1354:
1355: } while (bytesLeft);
1356:
1357: //
1358: // Write SGL length to ECB.
1359: //
1360:
1361: ecb->SglLength = descriptorCount * sizeof(SG_DESCRIPTOR);
1362:
1363: //
1364: // Write SGL address to ECB.
1365: //
1366:
1367: ecb->PhysicalSgl = physicalSgl;
1368:
1369: return;
1370:
1371: } // end A174xBuildSgl()
1372:
1373:
1374: VOID
1375: A174xBuildRequestSense(
1376: IN PVOID HwDeviceExtension,
1377: IN PSCSI_REQUEST_BLOCK Srb
1378: )
1379:
1380: /*++
1381:
1382: Routine Description:
1383:
1384: This routine is called when a request sense is detected. An adapter
1385: command is then built for a request sense. This is the
1386: only way to clear the contingent alligience condition that the adapter
1387: is always in following a check condition.
1388:
1389: Arguments:
1390:
1391: HwDeviceExtension - HBA miniport driver's adapter data storage
1392: Srb - IO request packet
1393:
1394: Return Value:
1395:
1396: TRUE is request succeeds.
1397:
1398: --*/
1399:
1400: {
1401: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
1402: PEISA_CONTROLLER eisaController = deviceExtension->EisaController;
1403: PECB ecb = Srb->SrbExtension;
1404: PSTATUS_BLOCK statusBlock = &ecb->StatusBlock;
1405: ULONG length;
1406:
1407: //
1408: // Set ECB command.
1409: //
1410:
1411: ecb->Command = ECB_COMMAND_READ_SENSE_INFO;
1412:
1413: //
1414: // Disable updating status block on success and enable
1415: // automatic request senes.
1416: //
1417:
1418: ecb->Flags[0] = ECB_FLAGS_DISABLE_STATUS_BLOCK |
1419: ECB_FLAGS_SUPPRESS_UNDERRUN;
1420:
1421: //
1422: // Set transfer direction bit.
1423: //
1424:
1425: ecb->Flags[1] = ECB_FLAGS_READ;
1426:
1427: //
1428: // Check if disconnect explicity forbidden.
1429: //
1430:
1431: if (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT) {
1432:
1433: ecb->Flags[1] |= ECB_FLAGS_NO_DISCONNECT;
1434: }
1435:
1436: //
1437: // Set LUN (bits 16, 17 and 18).
1438: //
1439:
1440: ecb->Flags[1] |= Srb->Lun;
1441:
1442: //
1443: // Set status block pointer.
1444: //
1445:
1446: ecb->StatusBlockAddress =
1447: ScsiPortConvertPhysicalAddressToUlong(
1448: ScsiPortGetPhysicalAddress(deviceExtension,
1449: NULL,
1450: statusBlock,
1451: &length));
1452:
1453: //
1454: // Set request sense address and length.
1455: //
1456:
1457: ecb->SenseInfoAddress = ScsiPortConvertPhysicalAddressToUlong(
1458: ScsiPortGetPhysicalAddress(deviceExtension,
1459: Srb,
1460: Srb->DataBuffer,
1461: &length));
1462:
1463: ASSERT(length >= Srb->DataTransferLength);
1464:
1465: ecb->SenseInfoLength = (UCHAR) Srb->DataTransferLength;
1466:
1467: //
1468: // Zero out next ECB, request sense info fields
1469: // and statuses in status block.
1470: //
1471:
1472: ecb->NextEcb = 0;
1473: statusBlock->HaStatus = 0;
1474: statusBlock->TargetStatus = 0;
1475:
1476: return;
1477:
1478: } // end A174xBuildRequestSense()
1479:
1480:
1481: BOOLEAN
1482: A174xSendCommand(
1483: IN PHW_DEVICE_EXTENSION DeviceExtension,
1484: IN UCHAR OperationCode,
1485: IN ULONG Address
1486: )
1487:
1488: /*++
1489:
1490: Routine Description:
1491:
1492: Send ECB or immediate command to AHA174X.
1493:
1494: Arguments:
1495:
1496: HwDeviceExtension - HBA miniport driver's adapter data storage
1497: OperationCode - value to be written to attention register
1498: Address - ECB address or immediate command
1499:
1500: Return Value:
1501:
1502: True if command sent.
1503: False if adapter never reached 'ready for next command' state.
1504:
1505: --*/
1506:
1507: {
1508: PEISA_CONTROLLER eisaController = DeviceExtension->EisaController;
1509: ULONG i;
1510:
1511: for (i=0; i<10; i++) {
1512:
1513: UCHAR status;
1514:
1515: status = ScsiPortReadPortUchar(&eisaController->Status);
1516:
1517: if ((status & MAILBOX_OUT_EMPTY) &&
1518: !(status & ADAPTER_BUSY)) {
1519:
1520: //
1521: // Adapter ready for next command.
1522: //
1523:
1524: break;
1525:
1526: } else {
1527:
1528: //
1529: // Stall 1 microsecond before trying again.
1530: //
1531:
1532: ScsiPortStallExecution(1);
1533: }
1534: }
1535:
1536: if (i == 10) {
1537:
1538: return FALSE;
1539: }
1540:
1541: //
1542: // Write ECB address or immediate command.
1543: //
1544:
1545: ScsiPortWritePortUlong(&eisaController->MailBoxOut, Address);
1546:
1547: //
1548: // Write operation code to attention register.
1549: //
1550:
1551: ScsiPortWritePortUchar(&eisaController->Attention, OperationCode);
1552:
1553: return TRUE;
1554:
1555: } // end A174xSendCommand()
1556:
1557: BOOLEAN
1558: Aha174xResetBus(
1559: IN PVOID HwDeviceExtension,
1560: IN ULONG PathId
1561: )
1562:
1563: /*++
1564:
1565: Routine Description:
1566:
1567: Reset Aha174x SCSI adapter and SCSI bus.
1568:
1569: Arguments:
1570:
1571: HwDeviceExtension - HBA miniport driver's adapter data storage
1572:
1573: Return Value:
1574:
1575: Nothing.
1576:
1577: --*/
1578:
1579: {
1580: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
1581: PEISA_CONTROLLER eisaController = deviceExtension->EisaController;
1582: ULONG j;
1583: UCHAR targetId;
1584: UCHAR lun;
1585:
1586:
1587: UNREFERENCED_PARAMETER(PathId);
1588:
1589: DebugPrint((2,"ResetBus: Reset Aha174x and SCSI bus\n"));
1590:
1591: //
1592: // Clean up pending requests.
1593: //
1594:
1595: if (deviceExtension->PendingSrb) {
1596:
1597: //
1598: // Notify the port driver that another request can be accepted.
1599: //
1600:
1601: ScsiPortNotification(NextRequest, deviceExtension);
1602:
1603: //
1604: // Clear the pending request. It will be completed by
1605: // ScsiPortCompleteRequest.
1606: //
1607:
1608: deviceExtension->PendingSrb = NULL;
1609:
1610: }
1611:
1612: //
1613: // Clear the reqeust counts.
1614: //
1615:
1616: for (targetId = 0; targetId < 8; targetId++) {
1617: for (lun = 0; lun < 8; lun++) {
1618:
1619: deviceExtension->RequestCount[targetId][lun] = 0;
1620: }
1621: }
1622:
1623: //
1624: // Complete all outstanding requests.
1625: //
1626:
1627: ScsiPortCompleteRequest(deviceExtension,
1628: 0,
1629: SP_UNTAGGED,
1630: SP_UNTAGGED,
1631: SRB_STATUS_BUS_RESET);
1632:
1633: targetId = deviceExtension->HostTargetId;
1634:
1635: //
1636: // Allow the adapter card to settle.
1637: //
1638:
1639: ScsiPortStallExecution(75000);
1640: ScsiPortReadPortUchar(&eisaController->Status);
1641: ScsiPortStallExecution(1);
1642:
1643: if (!A174xSendCommand(deviceExtension,
1644: (UCHAR)(IMMEDIATE_COMMAND | targetId),
1645: ECB_IMMEDIATE_RESET)) {
1646:
1647: //
1648: // Timed out waiting for adapter to become ready.
1649: //
1650:
1651: ScsiPortLogError(
1652: deviceExtension,
1653: NULL,
1654: 0,
1655: deviceExtension->HostTargetId,
1656: 0,
1657: SP_INTERNAL_ADAPTER_ERROR,
1658: 4 << 16
1659: );
1660:
1661: //
1662: // Adapter never reached state to receive command.
1663: // Try a hard reset by wiggling the control line.
1664: //
1665:
1666: ScsiPortWritePortUchar(&eisaController->Control, HARD_RESET);
1667:
1668: //
1669: // Wait at least 10 microseconds.
1670: //
1671:
1672: ScsiPortStallExecution(10);
1673:
1674: //
1675: // Clear the reset line now that it has been held for 10 us.
1676: //
1677:
1678: ScsiPortWritePortUchar(&eisaController->Control, 0);
1679:
1680: //
1681: // Write the attention register to wake up the firmware so that
1682: // it will clear the busy line in the status register.
1683: // The attention value written (0) is ignored by the controller
1684: // but will wakeup the firmware.
1685: //
1686:
1687: ScsiPortStallExecution(20000); // Add a little delay
1688: ScsiPortWritePortUchar(&eisaController->Attention, 0);
1689:
1690: //
1691: // Wait for busy to go low.
1692: //
1693:
1694: j = 0;
1695: while (ScsiPortReadPortUchar(&eisaController->Status) & ADAPTER_BUSY) {
1696:
1697: j++;
1698: if (j > 200000) {
1699:
1700: //
1701: // Busy has not gone low. Assume the card is gone.
1702: // Log the error and fail the request.
1703: //
1704:
1705:
1706: ScsiPortLogError(
1707: deviceExtension,
1708: NULL,
1709: 0,
1710: deviceExtension->HostTargetId,
1711: 0,
1712: SP_INTERNAL_ADAPTER_ERROR,
1713: 3 << 16
1714: );
1715:
1716: return FALSE;
1717:
1718: }
1719:
1720: ScsiPortStallExecution(10);
1721: }
1722: }
1723:
1724: return TRUE;
1725:
1726: } // end Aha174xResetBus()
1727:
1728:
1729: VOID
1730: A174xMapStatus(
1731: IN PHW_DEVICE_EXTENSION DeviceExtension,
1732: IN PSCSI_REQUEST_BLOCK Srb,
1733: IN PSTATUS_BLOCK StatusBlock
1734: )
1735:
1736: /*++
1737:
1738: Routine Description:
1739:
1740: Translate Aha174x error to SRB error.
1741:
1742: Arguments:
1743:
1744: SRB
1745: Status block for request completing with error.
1746:
1747: Return Value:
1748:
1749: Updated SRB
1750:
1751: --*/
1752:
1753: {
1754: ULONG logError = 0;
1755: UCHAR srbStatus;
1756: PECB ecb = Srb->SrbExtension;
1757:
1758:
1759: DebugPrint((2,
1760: "A174xMapStatus: Status word is %x\n",
1761: StatusBlock->StatusWord));
1762:
1763: if (StatusBlock->TargetStatus == SCSISTAT_CHECK_CONDITION) {
1764:
1765: //
1766: // A check condition occured. Set the srb status and process the
1767: // auto sense data.
1768: //
1769:
1770: Srb->SrbStatus = SRB_STATUS_ERROR;
1771:
1772: //
1773: // Set target SCSI status in SRB.
1774: //
1775:
1776: Srb->ScsiStatus = StatusBlock->TargetStatus;
1777:
1778: //
1779: // Update SRB with actual bytes transferred.
1780: //
1781:
1782: Srb->DataTransferLength -= StatusBlock->ResidualByteCount;
1783:
1784: if (StatusBlock->StatusWord & SB_STATUS_SENSE_INFORMATION) {
1785:
1786: //
1787: // Indicate the sense information is valid and update the length.
1788: //
1789:
1790: Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
1791: Srb->SenseInfoBufferLength = StatusBlock->RequestSenseLength;
1792: }
1793:
1794: return;
1795: }
1796:
1797: switch (StatusBlock->HaStatus) {
1798:
1799: case SB_HASTATUS_SELECTION_TIMEOUT:
1800: srbStatus = SRB_STATUS_SELECTION_TIMEOUT;
1801: break;
1802:
1803: case SB_HASTATUS_DATA_OVERUNDER_RUN:
1804: DebugPrint((1,"A174xMapStatus: Data over/underrun\n"));
1805:
1806: //
1807: // Update SRB with actual bytes transferred.
1808: //
1809:
1810: Srb->DataTransferLength -= StatusBlock->ResidualByteCount;
1811:
1812: srbStatus = SRB_STATUS_DATA_OVERRUN;
1813: break;
1814:
1815: case SB_HASTATUS_UNEXPECTED_BUS_FREE:
1816: DebugPrint((1,"A174xMapStatus: Unexpected bus free\n"));
1817: logError = SP_PROTOCOL_ERROR;
1818: srbStatus = SRB_STATUS_UNEXPECTED_BUS_FREE;
1819: break;
1820:
1821: case SB_HASTATUS_INVALID_BUS_PHASE:
1822: DebugPrint((1,"A174xMapStatus: Invalid bus phase\n"));
1823: logError = SP_PROTOCOL_ERROR;
1824: srbStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
1825: break;
1826:
1827: case SB_HASTATUS_TARGET_NOT_USED:
1828: DebugPrint((1,"A174xMapStatus: Target not used\n"));
1829: srbStatus = SRB_STATUS_NO_DEVICE;
1830: break;
1831:
1832: case SB_HASTATUS_INVALID_ECB:
1833: DebugPrint((1,"A174xMapStatus: Invalid ECB\n"));
1834: logError = SP_INTERNAL_ADAPTER_ERROR;
1835: srbStatus = SRB_STATUS_INVALID_REQUEST;
1836: break;
1837:
1838: case SB_HASTATUS_ADAPTER_HARDWARE_ERROR:
1839: DebugPrint((1,"A174xMapStatus: Hardware error\n"));
1840: logError = SP_INTERNAL_ADAPTER_ERROR;
1841: srbStatus = SRB_STATUS_ERROR;
1842: break;
1843:
1844: case SB_HASTATUS_ADAPTER_RESET_BUS:
1845: DebugPrint((1,"A174xMapStatus: Adapter reset bus\n"));
1846: srbStatus = SRB_STATUS_BUS_RESET;
1847: break;
1848:
1849: case SB_HASTATUS_DEVICE_RESET_BUS:
1850: DebugPrint((1,"A174xMapStatus: Device reset bus\n"));
1851: srbStatus = SRB_STATUS_BUS_RESET;
1852: break;
1853:
1854: case SB_HASTATUS_CHECKSUM_FAILURE:
1855: DebugPrint((1,"A174xMapStatus: Checksum failure\n"));
1856: logError = SP_INTERNAL_ADAPTER_ERROR;
1857: srbStatus = SRB_STATUS_ERROR;
1858: break;
1859:
1860: case SB_HASTATUS_ADAPTER_ABORTED:
1861: DebugPrint((1,"A174xMapStatus: Adapter aborted\n"));
1862: srbStatus = SRB_STATUS_ABORTED;
1863: break;
1864:
1865: case SB_HASTATUS_HOST_ABORTED:
1866: DebugPrint((1,"A174xMapStatus: Host aborted\n"));
1867: srbStatus = SRB_STATUS_ABORTED;
1868: break;
1869:
1870: case SB_HASTATUS_FW_NOT_DOWNLOADED:
1871: DebugPrint((1,"A174xMapStatus: Firmware not downloaded\n"));
1872: logError = SP_INTERNAL_ADAPTER_ERROR;
1873: srbStatus = SRB_STATUS_ERROR;
1874: break;
1875:
1876: case SB_HASTATUS_INVALID_SGL:
1877: DebugPrint((1,"A174xMapStatus: Invalid SGL\n"));
1878: logError = SP_INTERNAL_ADAPTER_ERROR;
1879: srbStatus = SRB_STATUS_INVALID_REQUEST;
1880: break;
1881:
1882: case SB_HASTATUS_REQUEST_SENSE_FAILED:
1883: DebugPrint((1,"A174xMapStatus: Request sense failed\n"));
1884: srbStatus = SRB_STATUS_ERROR;
1885: break;
1886:
1887: default:
1888:
1889: srbStatus = SRB_STATUS_ERROR;
1890:
1891: //
1892: // Check status block word.
1893: //
1894:
1895: if (StatusBlock->StatusWord & SB_STATUS_NO_ERROR) {
1896:
1897: //
1898: // This should never happen as this routine is only
1899: // called when there is an error.
1900: //
1901:
1902: DebugPrint((1,"A174xMapStatus: No error\n"));
1903: srbStatus = SRB_STATUS_SUCCESS;
1904: break;
1905:
1906: }
1907:
1908: //
1909: // Check for underrun.
1910: //
1911:
1912: if (StatusBlock->StatusWord & SB_STATUS_DATA_UNDERRUN) {
1913:
1914: DebugPrint((1,
1915: "A174xMapStatus: Data underrun indicated in status word\n"));
1916:
1917: //
1918: // Update SRB with actual bytes transferred.
1919: //
1920:
1921: Srb->DataTransferLength -= StatusBlock->ResidualByteCount;
1922: break;
1923: }
1924:
1925: //
1926: // Check for overrun.
1927: //
1928:
1929: if (StatusBlock->StatusWord & SB_STATUS_DATA_OVERRUN) {
1930:
1931: DebugPrint((1,
1932: "A174xMapStatus: Data overrun indicate in status word\n"));
1933: logError = SP_PROTOCOL_ERROR;
1934: break;
1935: }
1936:
1937: //
1938: // Check for initialization required.
1939: //
1940:
1941: if (StatusBlock->StatusWord & SB_STATUS_INIT_REQUIRED) {
1942: DebugPrint((1,
1943: "A174xMapStatus: Initialization required\n"));
1944: break;
1945: }
1946:
1947: //
1948: // Check for contingent allegience condition. If this happens
1949: // something is very wrong (because autorequest sense was indicated).
1950: //
1951:
1952: if (StatusBlock->StatusWord & SB_STATUS_EXT_CONT_ALLEGIANCE) {
1953:
1954: DebugPrint((1,
1955: "A174xMapStatus: Contingent allegiance condition\n"));
1956:
1957: ASSERT(0);
1958: }
1959:
1960: if (StatusBlock->StatusWord & SB_STATUS_MAJOR_ERROR) {
1961:
1962: DebugPrint((1,
1963: "A174xMapStatus: Major error indicated in status word\n"));
1964: break;
1965: }
1966:
1967: logError = SP_INTERNAL_ADAPTER_ERROR;
1968: break;
1969:
1970: } // end switch ...
1971:
1972: if (logError != 0) {
1973:
1974: //
1975: // Log error.
1976: //
1977:
1978: ScsiPortLogError(
1979: DeviceExtension,
1980: Srb,
1981: Srb->PathId,
1982: Srb->TargetId,
1983: Srb->Lun,
1984: logError,
1985: 2 << 16 | StatusBlock->HaStatus
1986: );
1987:
1988: }
1989:
1990: //
1991: // Set SRB status.
1992: //
1993:
1994: Srb->SrbStatus = srbStatus;
1995:
1996: //
1997: // Set target SCSI status in SRB.
1998: //
1999:
2000: Srb->ScsiStatus = StatusBlock->TargetStatus;
2001:
2002: return;
2003:
2004: } // end A174xMapStatus()
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.