Annotation of ntddk/src/scsi/aha174x/aha174x.c, revision 1.1.1.1

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()

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.